{"openapi":"3.1.0","info":{"title":"Meeting BaaS API","description":"API for managing meeting bots, calendar integrations, and webhooks","summary":"API for recording and transcribing video meetings across Zoom, Google Meet, and Microsoft Teams. Features include bot management, calendar integration, and transcription services.","version":"2.0.0","termsOfService":"https://meetingbaas.com/terms-and-conditions","contact":{"name":"Meeting BaaS Support","email":"support@meetingbaas.com"}},"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"x-meeting-baas-api-key","description":"Your Meeting BaaS API key. Get one from your account settings."}},"schemas":{"ErrorResponseInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/ErrorResponseInput","type":"object","properties":{"success":{"default":false,"type":"boolean","const":false},"error":{"description":"Human-readable error message","type":"string"},"code":{"description":"Error code for programmatic handling","type":"string"},"statusCode":{"description":"HTTP status code","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"message":{"description":"Human-readable error message","anyOf":[{"type":"string"},{"type":"null"}]},"details":{"description":"Additional error details (string or null)","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["error","code","statusCode"]},"ValidationErrorResponseInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/ValidationErrorResponseInput","type":"object","properties":{"success":{"default":false,"type":"boolean","const":false},"error":{"description":"Error name","type":"string"},"code":{"description":"Error code for programmatic handling","type":"string"},"statusCode":{"description":"HTTP status code","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"message":{"description":"Human-readable error message","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["error","code","statusCode"]},"CreateBotRequestBodyInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/CreateBotRequestBodyInput","type":"object","properties":{"bot_name":{"description":"The name of the bot.\n\nThis name will be displayed as the bot's name in the meeting.","example":"Meeting BaaS Bot","type":"string","minLength":1,"maxLength":255},"bot_image":{"description":"The bot's avatar image(s).\n\nAccepts a single HTTPS URL or an array of up to 5 HTTPS URLs pointing to image files (JPEG, PNG, or WebP). When multiple images are provided, they will be cycled based on the bot_image_config settings.","example":null,"default":null,"anyOf":[{"anyOf":[{"type":"string","format":"uri"},{"minItems":1,"maxItems":5,"type":"array","items":{"type":"string","format":"uri"}}]},{"type":"null"}]},"bot_image_config":{"description":"Configuration for how bot avatar images are displayed. Only relevant when multiple images are provided in bot_image.","example":null,"default":null,"anyOf":[{"type":"object","properties":{"loop_mode":{"description":"Controls how multiple bot images are cycled.\n\n- `auto`: Cycles through images at the interval specified by image_duration.\n- `bot_status`: Uses the first image when the bot joins, and the second image when recording starts. Only the first two images are used in this mode; additional images are ignored.","default":"auto","type":"string","enum":["auto","bot_status"]},"image_duration":{"description":"Duration in seconds each image is displayed before switching to the next. Only used when loop_mode is 'auto'.\n\nDefault: 30. Range: 10-120.","default":30,"type":"integer","minimum":10,"maximum":120}}},{"type":"null"}]},"meeting_url":{"description":"The URL of the meeting to join.\n\nMust be a valid HTTPS URL for a Microsoft Teams, Google Meet, or Zoom meeting.\n\nExample: \"https://zoom.us/j/123456789\" or \"https://meet.google.com/abc-defg-hij\"","example":"","type":"string","format":"uri"},"allow_multiple_bots":{"description":"Whether to allow multiple bots to join the same meeting.\n\nIf set to `false`, only a single bot will be allowed to join using the same meeting URL within the last 5 minutes. This prevents duplicate bots from joining the same meeting.\n\nIf set to `true` (default), multiple bots can join the same meeting URL.\n\nDefault: `true`","example":true,"default":true,"type":"boolean"},"recording_mode":{"description":"The recording mode of the bot.\n\nDetermines what the bot records during the meeting:\n\n- `speaker_view`: Records the speaker's view (default). Shows the active speaker or presenter.\n- `audio_only`: Records only the audio without video.\n- `gallery_view`: Records the entire gallery view (coming soon).\n\nDefault: `speaker_view`","example":"speaker_view","default":"speaker_view","type":"string","enum":["audio_only","speaker_view","gallery_view"]},"entry_message":{"description":"The message that the bot will send when it joins the meeting.\n\nThis message will be posted in the meeting chat when the bot successfully joins.\n\nAvailable for Google Meet, Microsoft Teams, and Zoom meetings.\n\nMaximum: 500 characters","example":"Hello! I'm here to record this meeting.","default":null,"anyOf":[{"type":"string","maxLength":500},{"type":"null"}]},"timeout_config":{"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.","default":{"waiting_room_timeout":600,"no_one_joined_timeout":600,"silence_timeout":600},"type":"object","properties":{"waiting_room_timeout":{"description":"The timeout in seconds for the bot to wait in the waiting room before leaving the meeting.\n\nIf the bot is placed in a waiting room and not admitted within this time, it will leave the meeting.\n\nNote: Google Meet has its own waiting room timeout (approximately 10 minutes). Setting a higher value for Google Meet meetings will have no effect, as Google Meet will deny entry to the bot after its own timeout.\n\nDefault: 600 seconds (10 minutes)\nMinimum: 2 minutes\nMaximum: 30 minutes","example":600,"default":600,"type":"integer","minimum":120,"maximum":1800},"no_one_joined_timeout":{"description":"The timeout in seconds for the bot to wait for participants to join before leaving the meeting.\n\nIf no participants join the meeting within this time after the bot joins, the bot will leave the meeting. Only applicable for Google Meet and Microsoft Teams meetings.\n\nDefault: 600 seconds (10 minutes)\nMinimum: 2 minutes\nMaximum: 30 minutes","example":600,"default":600,"type":"integer","minimum":120,"maximum":1800},"silence_timeout":{"description":"The timeout in seconds for the bot to wait for silence before leaving the meeting.\n\nIf no audio is detected for this duration after the bot joins, the bot will leave the meeting. Only applicable for Google Meet and Microsoft Teams meetings.\n\nDefault: 600 seconds (10 minutes)\nMinimum: 5 minutes\nMaximum: 30 minutes","example":600,"default":600,"type":"integer","minimum":300,"maximum":1800}}},"zoom_config":{"description":"Zoom-only configuration for authentication and join method.\n\n- **credential_id**: Use a stored Zoom credential (OBF token fetched by the bot from the API server).\n- **credential_user_id**: Resolve a stored credential by Zoom user ID.\n- **obf_token**: Provide a direct OBF token (one-off join).\n- **obf_token_url**: URL that returns an OBF token when the bot joins.\n- **zak_token_url**: URL that returns a ZAK for joining without the host.\n\nLeave `null` for Google Meet and Microsoft Teams.","example":null,"default":null,"anyOf":[{"type":"object","properties":{"credential_id":{"description":"UUID of a stored Zoom credential (created via Zoom credentials API). The bot will fetch the OBF token from the API server using this ID. Use this when you have saved a Zoom OAuth credential and want the bot to join on behalf of that user.","type":"string","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)$"},"credential_user_id":{"description":"Zoom user ID (e.g. from the Zoom profile) to look up a stored credential by user. The API server will resolve this to a credential_id. Use when you have multiple credentials and want to target a specific user.","type":"string"},"obf_token":{"description":"Direct OBF (On-Behalf-Of) token. Use this to join a Zoom meeting as a specific user without storing a credential. The token is a JWT issued by Zoom; the bot uses it once to join. Suitable for short-lived or one-off joins. For recurring use, prefer credential_id or obf_token_url.","type":"string"},"obf_token_url":{"description":"URL that returns an OBF token at join time. The bot will make a GET request with query params: bot_uuid (bot UUID) and extra (URL-encoded JSON of the run's extra payload). Use these to identify which bot/run is requesting the token. Response must be plain text (ASCII) containing the OBF token. Timeout: 15 seconds.","type":"string","format":"uri"},"zak_token_url":{"description":"URL to get the Zoom ZAK (Zoom Access Token). The bot makes a GET request with query params: bot_uuid and extra (URL-encoded JSON). Use these to identify which bot/run is requesting the token. Response must be plain text (ASCII) with the raw ZAK. See https://developers.zoom.us/docs/api/users/#tag/users/get/users/me/zak. Timeout: 15 seconds.","type":"string","format":"uri"}}},{"type":"null"}]},"extra":{"description":"An optional extra configuration object for the bot.\n\nThis object can contain any custom key-value pairs that you want to associate with the bot. The data will be:\n\n- Included in all webhook event payloads (if a webhook endpoint is configured)\n- Part of the callback payload (if callback is enabled)\n- Returned when fetching the bot's details via the API\n\nUseful for storing custom metadata, tracking information, or any other data you need to correlate with the bot.","example":null,"default":null,"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]},"streaming_enabled":{"description":"Enable audio streaming for this bot. When enabled, the streaming_config property is used to provide the configuration.","default":false,"type":"boolean"},"streaming_config":{"default":null,"anyOf":[{"example":null,"type":"object","properties":{"input_url":{"description":"Websocket stream URL, which receives the audio sent to the bot, and the bot will stream the audio to the meeting.","example":null,"default":null,"anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"output_url":{"description":"Websocket stream URL, which the bot sends the audio to. This is used to stream the output audio to a destination.","example":null,"default":null,"anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"audio_frequency":{"description":"The audio frequency in Hz. Supported values: 24000 (default), 32000, 48000 Hz.","example":null,"default":24000,"anyOf":[{"description":"Audio frequency in Hz. Supported values: 16000, 24000 (default), 32000, 48000 Hz.","anyOf":[{"type":"number","const":16000},{"type":"number","const":24000},{"type":"number","const":32000},{"type":"number","const":48000}]},{"type":"null"}]}}},{"type":"null"}]},"transcription_enabled":{"description":"Enable transcription for this bot. When enabled, the transcription_config property is used to customise the transcription provider and parameters.","default":false,"type":"boolean"},"transcription_config":{"default":null,"anyOf":[{"example":{"provider":"gladia","api_key":null,"custom_params":null},"type":"object","properties":{"provider":{"description":"The speech to text provider to use for the bot. The default and only supported provider is 'gladia'. More providers will be supported in the future.","default":"gladia","type":"string","enum":["gladia"]},"api_key":{"description":"The API key to use for the speech to text provider. This can be provided to use your own API key for the speech to text provider. It consumes less tokens than using the default API key. It is available on 'Pro' plans and above.","example":null,"default":null,"anyOf":[{"type":"string"},{"type":"null"}]},"custom_params":{"description":"Custom parameters for the transcription provider. See the transcription provider's documentation for available options. For Gladia, see https://docs.gladia.io/api-reference/v2/pre-recorded/init","example":null,"default":null,"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]}}},{"type":"null"}]},"callback_enabled":{"description":"Enable callback for this bot. When enabled, the callback_config property is used to provide the configuration.","default":false,"type":"boolean"},"callback_config":{"default":null,"anyOf":[{"example":null,"type":"object","properties":{"url":{"description":"The URL to be called upon the completion or failure of the bot.","type":"string","format":"uri"},"secret":{"description":"To ensure that you can validate the callback, this secret will be added to the request in the 'x-mb-secret' header","example":null,"default":null,"anyOf":[{"type":"string"},{"type":"null"}]},"method":{"description":"The HTTP method to use for the callback. Allowed values are 'POST' or 'PUT'.","default":"POST","type":"string","enum":["POST","PUT"]}},"required":["url"]},{"type":"null"}]}},"required":["bot_name","meeting_url"]},"BatchCreateBotsRequestBodyInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/BatchCreateBotsRequestBodyInput","minItems":1,"maxItems":100,"type":"array","items":{"$ref":"#/components/schemas/CreateBotRequestBodyInput"}},"RetryCallbackRequestBodyInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/RetryCallbackRequestBodyInput","description":"Optional callback configuration to override the bot's configured callback.\n\nIf provided, all fields must be included and these values will be used instead of the bot's original callback configuration. If omitted (null), the bot's original callback configuration will be used.\n\n- `url`: Custom callback URL (overrides configured URL)\n- `method`: HTTP method (`POST` or `PUT`, default: `POST`)\n- `secret`: Custom HMAC secret (overrides configured secret, sent in `x-mb-secret` header)","default":null,"anyOf":[{"example":null,"type":"object","properties":{"url":{"description":"The URL to be called upon the completion or failure of the bot.","type":"string","format":"uri"},"secret":{"description":"To ensure that you can validate the callback, this secret will be added to the request in the 'x-mb-secret' header","example":null,"default":null,"anyOf":[{"type":"string"},{"type":"null"}]},"method":{"description":"The HTTP method to use for the callback. Allowed values are 'POST' or 'PUT'.","default":"POST","type":"string","enum":["POST","PUT"]}},"required":["url"]},{"type":"null"}]},"CreateBotResponseInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/CreateBotResponseInput","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"object","properties":{"bot_id":{"description":"The UUID of the created bot","type":"string","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)$"}},"required":["bot_id"]}},"required":["success","data"]},"BatchCreateBotResponseInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/BatchCreateBotResponseInput","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"description":"Successfully created bots","type":"array","items":{"type":"object","properties":{"index":{"description":"0-based index of the item in the request array","type":"integer","minimum":0,"maximum":9007199254740991},"bot_id":{"description":"The UUID of the created bot","type":"string","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)$"},"extra":{"description":"Custom metadata from the request (for correlation)","anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]}},"required":["index","bot_id","extra"]}},"errors":{"description":"Bots that failed to create (empty array if all succeeded)","type":"array","items":{"type":"object","properties":{"index":{"description":"0-based index of the item in the request array","type":"integer","minimum":0,"maximum":9007199254740991},"code":{"description":"Error code for programmatic handling","type":"string"},"message":{"description":"Human-readable error message","type":"string"},"details":{"description":"Additional error details (null if no additional details)","anyOf":[{"type":"string"},{"type":"null"}]},"extra":{"description":"Custom metadata from the request (for correlation)","anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]}},"required":["index","code","message","details","extra"]}}},"required":["success","data","errors"]},"ListBotsResponseInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/ListBotsResponseInput","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"array","items":{"type":"object","properties":{"bot_id":{"description":"The UUID of the bot","type":"string","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)$"},"bot_name":{"description":"The name of the bot","type":"string"},"meeting_url":{"description":"The URL of the meeting","type":"string","format":"uri"},"meeting_platform":{"description":"The platform of the meeting (zoom, meet, or teams)","type":"string","enum":["zoom","meet","teams"]},"extra":{"description":"Custom metadata associated with the bot","anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]},"duration":{"description":"Duration of the meeting in seconds (null if meeting hasn't ended)","anyOf":[{"type":"number"},{"type":"null"}]},"created_at":{"description":"ISO 8601 timestamp when the bot was created","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"ended_at":{"description":"ISO 8601 timestamp when the bot ended (null if still active)","anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"joined_at":{"description":"ISO 8601 timestamp when the bot joined the meeting (null if not joined yet)","anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"exited_at":{"description":"ISO 8601 timestamp when the bot exited the meeting (null if not exited yet)","anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"status":{"description":"The current status of the bot","type":"string","enum":["queued","transcribing","completed","failed","joining_call","in_waiting_room","in_waiting_for_host","in_call_not_recording","in_call_recording","recording_paused","recording_resumed","call_ended","recording_succeeded","recording_failed","api_request_stop","bot_rejected","bot_removed","bot_removed_too_early","waiting_room_timeout","invalid_meeting_url","meeting_error"]},"error_code":{"description":"Error code if the bot failed (null if no error)","anyOf":[{"type":"string"},{"type":"null"}]},"error_message":{"description":"Human-readable error message if the bot failed (null if no error)","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["bot_id","bot_name","meeting_url","meeting_platform","extra","duration","created_at","ended_at","joined_at","exited_at","status","error_code","error_message"]}},"cursor":{"description":"Cursor for the next page (null if no more pages)","anyOf":[{"type":"string"},{"type":"null"}]},"prev_cursor":{"description":"Cursor for the previous page (null if on first page)","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["success","data","cursor","prev_cursor"]},"GetBotDetailsResponseInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/GetBotDetailsResponseInput","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"object","properties":{"bot_id":{"description":"The UUID of the bot","type":"string","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)$"},"bot_name":{"description":"The name of the bot","type":"string"},"meeting_url":{"description":"The URL of the meeting","type":"string","format":"uri"},"meeting_platform":{"description":"The platform of the meeting","type":"string","enum":["zoom","meet","teams"]},"recording_mode":{"description":"The recording mode used by the bot","type":"string","enum":["audio_only","speaker_view","gallery_view"]},"status":{"description":"The current status of the bot","type":"string","enum":["queued","transcribing","completed","failed","joining_call","in_waiting_room","in_waiting_for_host","in_call_not_recording","in_call_recording","recording_paused","recording_resumed","call_ended","recording_succeeded","recording_failed","api_request_stop","bot_rejected","bot_removed","bot_removed_too_early","waiting_room_timeout","invalid_meeting_url","meeting_error"]},"created_at":{"description":"ISO 8601 timestamp when the bot was created","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"joined_at":{"description":"ISO 8601 timestamp when the bot joined the meeting (null if not joined yet)","anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"exited_at":{"description":"ISO 8601 timestamp when the bot exited the meeting (null if not exited yet)","anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"duration_seconds":{"description":"Duration of the meeting in seconds (null if meeting hasn't ended)","anyOf":[{"type":"number"},{"type":"null"}]},"participants":{"description":"List of participants who joined the meeting with their names and metadata","type":"array","items":{"type":"object","properties":{"name":{"description":"Participant's name (full name or display name)","type":"string"},"id":{"description":"Sequential participant ID (1, 2, 3...). Null if not available","anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"display_name":{"description":"Display name shown in UI (if different from name)","type":"string"},"profile_picture":{"description":"Profile picture URL (if available)","type":"string","format":"uri"}},"required":["name","id"]}},"speakers":{"description":"List of speakers identified in the meeting with their names and metadata","type":"array","items":{"type":"object","properties":{"name":{"description":"Participant's name (full name or display name)","type":"string"},"id":{"description":"Sequential participant ID (1, 2, 3...). Null if not available","anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"display_name":{"description":"Display name shown in UI (if different from name)","type":"string"},"profile_picture":{"description":"Profile picture URL (if available)","type":"string","format":"uri"}},"required":["name","id"]}},"artifacts_deleted":{"description":"Whether the artifacts have been deleted","type":"boolean"},"video":{"description":"Signed URL to the video recording (valid for 4 hours, null if not available)","anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"audio":{"description":"Signed URL to the audio recording (valid for 4 hours, null if not available)","anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"diarization":{"description":"Signed URL to the diarization file (valid for 4 hours, null if not available)","anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"raw_transcription":{"description":"Signed URL to the raw transcription file (valid for 4 hours, null if not available)","anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"transcription":{"description":"Signed URL to the transcription file (valid for 4 hours, null if not available)","anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"chat_messages":{"description":"Signed URL to the chat messages JSON file (valid for 4 hours, null if not available)","anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"transcription_ids":{"description":"Array of transcription job IDs from the transcription provider","anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}]},"transcription_provider":{"description":"The transcription provider used (null if transcription is disabled or provider is 'none')","anyOf":[{"type":"string","enum":["gladia"]},{"type":"null"}]},"error_code":{"description":"Error code if the bot failed (null if no error)","anyOf":[{"type":"string"},{"type":"null"}]},"error_message":{"description":"Human-readable error message if the bot failed (null if no error)","anyOf":[{"type":"string"},{"type":"null"}]},"extra":{"description":"Custom metadata associated with the bot","anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]},"zoom_config":{"description":"Zoom configuration for this bot (null if not a Zoom bot or no zoom config provided)","anyOf":[{"type":"object","properties":{"credential_id":{"description":"UUID of the stored Zoom credential","anyOf":[{"type":"string","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":"null"}]},"credential_user_id":{"description":"Zoom user ID used to look up the credential","anyOf":[{"type":"string"},{"type":"null"}]},"obf_token_url":{"description":"URL that returns an OBF token at join time","anyOf":[{"type":"string"},{"type":"null"}]},"zak_token_url":{"description":"URL that returns a ZAK token at join time","anyOf":[{"type":"string"},{"type":"null"}]}}},{"type":"null"}]}},"required":["bot_id","bot_name","meeting_url","meeting_platform","recording_mode","status","created_at","joined_at","exited_at","duration_seconds","participants","speakers","artifacts_deleted","video","audio","diarization","raw_transcription","transcription","chat_messages","transcription_ids","transcription_provider","error_code","error_message","extra","zoom_config"]}},"required":["success","data"]},"GetBotStatusResponseInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/GetBotStatusResponseInput","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"object","properties":{"bot_id":{"description":"The UUID of the bot","type":"string","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)$"},"status":{"description":"The current status of the bot","type":"string","enum":["queued","transcribing","completed","failed","joining_call","in_waiting_room","in_waiting_for_host","in_call_not_recording","in_call_recording","recording_paused","recording_resumed","call_ended","recording_succeeded","recording_failed","api_request_stop","bot_rejected","bot_removed","bot_removed_too_early","waiting_room_timeout","invalid_meeting_url","meeting_error"]},"transcription_status":{"description":"The current transcription status","type":"string","enum":["queued","processing","done","error","not-applicable","not-started"]},"updated_at":{"description":"ISO 8601 timestamp when the status was last updated","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["bot_id","status","transcription_status","updated_at"]}},"required":["success","data"]},"GetBotScreenshotsResponseInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/GetBotScreenshotsResponseInput","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"array","items":{"type":"object","properties":{"screenshot_id":{"description":"The index of the screenshot (1-based)","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"url":{"description":"Signed URL to the screenshot (valid for 4 hours)","type":"string","format":"uri"}},"required":["screenshot_id","url"]}},"cursor":{"description":"Cursor for the next page (null if no more pages)","anyOf":[{"type":"string"},{"type":"null"}]},"prev_cursor":{"description":"Cursor for the previous page (null if on first page)","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["success","data","cursor","prev_cursor"]},"LeaveBotResponseInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/LeaveBotResponseInput","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"object","properties":{"message":{"description":"Success message","type":"string"}},"required":["message"]}},"required":["success","data"]},"DeleteBotDataResponseInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/DeleteBotDataResponseInput","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"object","properties":{"message":{"description":"Success message","type":"string"}},"required":["message"]}},"required":["success","data"]},"ResendFinalWebhookResponseInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/ResendFinalWebhookResponseInput","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"object","properties":{"message":{"description":"Success message","type":"string"}},"required":["message"]}},"required":["success","data"]},"RetryCallbackResponseInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/RetryCallbackResponseInput","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"object","properties":{"message":{"description":"Success message","type":"string"}},"required":["message"]}},"required":["success","data"]},"CreateScheduledBotRequestBodyInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/CreateScheduledBotRequestBodyInput","allOf":[{"$ref":"#/components/schemas/CreateBotRequestBodyInput"},{"type":"object","properties":{"join_at":{"description":"ISO8601 timestamp when the bot should join the meeting.\n\nCannot be in the past (with 1 minute leeway) and cannot be more than 90 days in the future.\n\nExample: \"2025-12-25T10:00:00Z\"","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["join_at"]}]},"BatchCreateScheduledBotsRequestBodyInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/BatchCreateScheduledBotsRequestBodyInput","minItems":1,"maxItems":100,"type":"array","items":{"$ref":"#/components/schemas/CreateScheduledBotRequestBodyInput"}},"UpdateScheduledBotRequestBodyInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/UpdateScheduledBotRequestBodyInput","type":"object","properties":{"bot_name":{"description":"The name of the bot.\n\nThis name will be displayed as the bot's name in the meeting.","example":"Meeting BaaS Bot","type":"string","minLength":1,"maxLength":255},"bot_image":{"description":"The bot's avatar image(s).\n\nAccepts a single HTTPS URL or an array of up to 5 HTTPS URLs pointing to image files (JPEG, PNG, or WebP). When multiple images are provided, they will be cycled based on the bot_image_config settings.","example":null,"default":null,"anyOf":[{"anyOf":[{"type":"string","format":"uri"},{"minItems":1,"maxItems":5,"type":"array","items":{"type":"string","format":"uri"}}]},{"type":"null"}]},"bot_image_config":{"description":"Configuration for how bot avatar images are displayed. Only relevant when multiple images are provided in bot_image.","example":null,"default":null,"anyOf":[{"type":"object","properties":{"loop_mode":{"description":"Controls how multiple bot images are cycled.\n\n- `auto`: Cycles through images at the interval specified by image_duration.\n- `bot_status`: Uses the first image when the bot joins, and the second image when recording starts. Only the first two images are used in this mode; additional images are ignored.","default":"auto","type":"string","enum":["auto","bot_status"]},"image_duration":{"description":"Duration in seconds each image is displayed before switching to the next. Only used when loop_mode is 'auto'.\n\nDefault: 30. Range: 10-120.","default":30,"type":"integer","minimum":10,"maximum":120}}},{"type":"null"}]},"meeting_url":{"description":"The URL of the meeting to join.\n\nMust be a valid HTTPS URL for a Microsoft Teams, Google Meet, or Zoom meeting.\n\nExample: \"https://zoom.us/j/123456789\" or \"https://meet.google.com/abc-defg-hij\"","example":"","type":"string","format":"uri"},"allow_multiple_bots":{"description":"Whether to allow multiple bots to join the same meeting.\n\nIf set to `false`, only a single bot will be allowed to join using the same meeting URL within the last 5 minutes. This prevents duplicate bots from joining the same meeting.\n\nIf set to `true` (default), multiple bots can join the same meeting URL.\n\nDefault: `true`","example":true,"default":true,"type":"boolean"},"recording_mode":{"description":"The recording mode of the bot.\n\nDetermines what the bot records during the meeting:\n\n- `speaker_view`: Records the speaker's view (default). Shows the active speaker or presenter.\n- `audio_only`: Records only the audio without video.\n- `gallery_view`: Records the entire gallery view (coming soon).\n\nDefault: `speaker_view`","example":"speaker_view","default":"speaker_view","type":"string","enum":["audio_only","speaker_view","gallery_view"]},"entry_message":{"description":"The message that the bot will send when it joins the meeting.\n\nThis message will be posted in the meeting chat when the bot successfully joins.\n\nAvailable for Google Meet, Microsoft Teams, and Zoom meetings.\n\nMaximum: 500 characters","example":"Hello! I'm here to record this meeting.","default":null,"anyOf":[{"type":"string","maxLength":500},{"type":"null"}]},"timeout_config":{"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.","default":{"waiting_room_timeout":600,"no_one_joined_timeout":600,"silence_timeout":600},"type":"object","properties":{"waiting_room_timeout":{"description":"The timeout in seconds for the bot to wait in the waiting room before leaving the meeting.\n\nIf the bot is placed in a waiting room and not admitted within this time, it will leave the meeting.\n\nNote: Google Meet has its own waiting room timeout (approximately 10 minutes). Setting a higher value for Google Meet meetings will have no effect, as Google Meet will deny entry to the bot after its own timeout.\n\nDefault: 600 seconds (10 minutes)\nMinimum: 2 minutes\nMaximum: 30 minutes","example":600,"default":600,"type":"integer","minimum":120,"maximum":1800},"no_one_joined_timeout":{"description":"The timeout in seconds for the bot to wait for participants to join before leaving the meeting.\n\nIf no participants join the meeting within this time after the bot joins, the bot will leave the meeting. Only applicable for Google Meet and Microsoft Teams meetings.\n\nDefault: 600 seconds (10 minutes)\nMinimum: 2 minutes\nMaximum: 30 minutes","example":600,"default":600,"type":"integer","minimum":120,"maximum":1800},"silence_timeout":{"description":"The timeout in seconds for the bot to wait for silence before leaving the meeting.\n\nIf no audio is detected for this duration after the bot joins, the bot will leave the meeting. Only applicable for Google Meet and Microsoft Teams meetings.\n\nDefault: 600 seconds (10 minutes)\nMinimum: 5 minutes\nMaximum: 30 minutes","example":600,"default":600,"type":"integer","minimum":300,"maximum":1800}}},"zoom_config":{"description":"Zoom-only configuration for authentication and join method.\n\n- **credential_id**: Use a stored Zoom credential (OBF token fetched by the bot from the API server).\n- **credential_user_id**: Resolve a stored credential by Zoom user ID.\n- **obf_token**: Provide a direct OBF token (one-off join).\n- **obf_token_url**: URL that returns an OBF token when the bot joins.\n- **zak_token_url**: URL that returns a ZAK for joining without the host.\n\nLeave `null` for Google Meet and Microsoft Teams.","example":null,"default":null,"anyOf":[{"type":"object","properties":{"credential_id":{"description":"UUID of a stored Zoom credential (created via Zoom credentials API). The bot will fetch the OBF token from the API server using this ID. Use this when you have saved a Zoom OAuth credential and want the bot to join on behalf of that user.","type":"string","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)$"},"credential_user_id":{"description":"Zoom user ID (e.g. from the Zoom profile) to look up a stored credential by user. The API server will resolve this to a credential_id. Use when you have multiple credentials and want to target a specific user.","type":"string"},"obf_token":{"description":"Direct OBF (On-Behalf-Of) token. Use this to join a Zoom meeting as a specific user without storing a credential. The token is a JWT issued by Zoom; the bot uses it once to join. Suitable for short-lived or one-off joins. For recurring use, prefer credential_id or obf_token_url.","type":"string"},"obf_token_url":{"description":"URL that returns an OBF token at join time. The bot will make a GET request with query params: bot_uuid (bot UUID) and extra (URL-encoded JSON of the run's extra payload). Use these to identify which bot/run is requesting the token. Response must be plain text (ASCII) containing the OBF token. Timeout: 15 seconds.","type":"string","format":"uri"},"zak_token_url":{"description":"URL to get the Zoom ZAK (Zoom Access Token). The bot makes a GET request with query params: bot_uuid and extra (URL-encoded JSON). Use these to identify which bot/run is requesting the token. Response must be plain text (ASCII) with the raw ZAK. See https://developers.zoom.us/docs/api/users/#tag/users/get/users/me/zak. Timeout: 15 seconds.","type":"string","format":"uri"}}},{"type":"null"}]},"extra":{"description":"An optional extra configuration object for the bot.\n\nThis object can contain any custom key-value pairs that you want to associate with the bot. The data will be:\n\n- Included in all webhook event payloads (if a webhook endpoint is configured)\n- Part of the callback payload (if callback is enabled)\n- Returned when fetching the bot's details via the API\n\nUseful for storing custom metadata, tracking information, or any other data you need to correlate with the bot.","example":null,"default":null,"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]},"streaming_enabled":{"description":"Enable audio streaming for this bot. When enabled, the streaming_config property is used to provide the configuration.","default":false,"type":"boolean"},"streaming_config":{"default":null,"anyOf":[{"example":null,"type":"object","properties":{"input_url":{"description":"Websocket stream URL, which receives the audio sent to the bot, and the bot will stream the audio to the meeting.","example":null,"default":null,"anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"output_url":{"description":"Websocket stream URL, which the bot sends the audio to. This is used to stream the output audio to a destination.","example":null,"default":null,"anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"audio_frequency":{"description":"The audio frequency in Hz. Supported values: 24000 (default), 32000, 48000 Hz.","example":null,"default":24000,"anyOf":[{"description":"Audio frequency in Hz. Supported values: 16000, 24000 (default), 32000, 48000 Hz.","anyOf":[{"type":"number","const":16000},{"type":"number","const":24000},{"type":"number","const":32000},{"type":"number","const":48000}]},{"type":"null"}]}}},{"type":"null"}]},"transcription_enabled":{"description":"Enable transcription for this bot. When enabled, the transcription_config property is used to customise the transcription provider and parameters.","default":false,"type":"boolean"},"transcription_config":{"default":null,"anyOf":[{"example":{"provider":"gladia","api_key":null,"custom_params":null},"type":"object","properties":{"provider":{"description":"The speech to text provider to use for the bot. The default and only supported provider is 'gladia'. More providers will be supported in the future.","default":"gladia","type":"string","enum":["gladia"]},"api_key":{"description":"The API key to use for the speech to text provider. This can be provided to use your own API key for the speech to text provider. It consumes less tokens than using the default API key. It is available on 'Pro' plans and above.","example":null,"default":null,"anyOf":[{"type":"string"},{"type":"null"}]},"custom_params":{"description":"Custom parameters for the transcription provider. See the transcription provider's documentation for available options. For Gladia, see https://docs.gladia.io/api-reference/v2/pre-recorded/init","example":null,"default":null,"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]}}},{"type":"null"}]},"callback_enabled":{"description":"Enable callback for this bot. When enabled, the callback_config property is used to provide the configuration.","default":false,"type":"boolean"},"callback_config":{"default":null,"anyOf":[{"example":null,"type":"object","properties":{"url":{"description":"The URL to be called upon the completion or failure of the bot.","type":"string","format":"uri"},"secret":{"description":"To ensure that you can validate the callback, this secret will be added to the request in the 'x-mb-secret' header","example":null,"default":null,"anyOf":[{"type":"string"},{"type":"null"}]},"method":{"description":"The HTTP method to use for the callback. Allowed values are 'POST' or 'PUT'.","default":"POST","type":"string","enum":["POST","PUT"]}},"required":["url"]},{"type":"null"}]},"join_at":{"description":"Update the scheduled join time.\n\nISO8601 format. Must be at least 4 minutes in the future and cannot be more than 90 days in the future.\n\nExample: \"2025-12-25T10:00:00Z\"","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}}},"CreateScheduledBotResponseInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/CreateScheduledBotResponseInput","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"object","properties":{"bot_id":{"description":"The UUID of the created scheduled bot","type":"string","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)$"}},"required":["bot_id"]}},"required":["success","data"]},"BatchCreateScheduledBotResponseInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/BatchCreateScheduledBotResponseInput","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"description":"Scheduled bots that were successfully created","type":"array","items":{"type":"object","properties":{"index":{"description":"0-based index of the item in the request array","type":"integer","minimum":0,"maximum":9007199254740991},"bot_id":{"description":"The UUID of the created scheduled bot","type":"string","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)$"},"extra":{"description":"Custom metadata from the request (null if not provided)","anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]}},"required":["index","bot_id","extra"]}},"errors":{"description":"Scheduled bots that failed to create (empty array if all succeeded)","type":"array","items":{"type":"object","properties":{"index":{"description":"0-based index of the item in the request array","type":"integer","minimum":0,"maximum":9007199254740991},"code":{"description":"Error code for programmatic handling","type":"string"},"message":{"description":"Human-readable error message","type":"string"},"details":{"description":"Additional error details (null if not available)","anyOf":[{"type":"string"},{"type":"null"}]},"extra":{"description":"Custom metadata from the request (null if not provided)","anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]}},"required":["index","code","message","details","extra"]}}},"required":["success","data","errors"]},"ListScheduledBotsResponseInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/ListScheduledBotsResponseInput","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"array","items":{"type":"object","properties":{"bot_id":{"description":"The UUID of the scheduled bot","type":"string","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)$"},"bot_name":{"description":"The name of the scheduled bot","type":"string"},"meeting_url":{"description":"The URL of the meeting","type":"string"},"meeting_platform":{"description":"The platform of the meeting","type":"string","enum":["zoom","meet","teams"]},"join_at":{"description":"ISO 8601 timestamp when the bot should join the meeting","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"status":{"description":"The current status of the scheduled bot","type":"string","enum":["scheduled","cancelled","completed","failed"]},"extra":{"description":"Custom metadata associated with the scheduled bot","anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]},"created_at":{"description":"ISO 8601 timestamp when the scheduled bot was created","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"updated_at":{"description":"ISO 8601 timestamp when the scheduled bot was last updated","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["bot_id","bot_name","meeting_url","meeting_platform","join_at","status","extra","created_at","updated_at"]}},"cursor":{"description":"Cursor for the next page (null if no more pages)","anyOf":[{"type":"string"},{"type":"null"}]},"prev_cursor":{"description":"Cursor for the previous page (null if on first page)","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["success","data","cursor","prev_cursor"]},"GetScheduledBotResponseInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/GetScheduledBotResponseInput","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"object","properties":{"bot_id":{"description":"The UUID of the scheduled bot","type":"string","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)$"},"bot_name":{"description":"The name of the scheduled bot","type":"string"},"bot_image":{"description":"The image URL for the bot (null if not set)","anyOf":[{"type":"string"},{"type":"null"}]},"meeting_url":{"description":"The URL of the meeting","type":"string"},"meeting_platform":{"description":"The platform of the meeting","type":"string","enum":["zoom","meet","teams"]},"recording_mode":{"description":"The recording mode for the bot","type":"string","enum":["audio_only","speaker_view","gallery_view"]},"join_at":{"description":"ISO 8601 timestamp when the bot should join the meeting","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"status":{"description":"The current status of the scheduled bot","type":"string","enum":["scheduled","cancelled","completed","failed"]},"created_at":{"description":"ISO 8601 timestamp when the scheduled bot was created","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"updated_at":{"description":"ISO 8601 timestamp when the scheduled bot was last updated","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"cancelled_at":{"description":"ISO 8601 timestamp when the scheduled bot was cancelled (null if not cancelled)","anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"allow_multiple_bots":{"description":"Whether multiple bots are allowed in the meeting","type":"boolean"},"entry_message":{"description":"Custom message to send when bot joins (null if not set)","anyOf":[{"type":"string"},{"type":"null"}]},"timeout_config":{"type":"object","properties":{"waiting_room_timeout":{"description":"Timeout in seconds for waiting room (null if not set)","anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"no_one_joined_timeout":{"description":"Timeout in seconds if no one joins (null if not set)","anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]}},"required":["waiting_room_timeout","no_one_joined_timeout"]},"transcription_config":{"description":"Transcription configuration (null if transcription is disabled)","anyOf":[{"type":"object","properties":{"enabled":{"type":"boolean","const":true},"provider":{"type":"string","enum":["gladia"]},"custom_params":{"description":"Custom parameters for transcription (null if not set)","anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]}},"required":["enabled","provider","custom_params"]},{"type":"null"}]},"streaming_config":{"description":"Streaming configuration (null if streaming is disabled)","anyOf":[{"type":"object","properties":{"enabled":{"type":"boolean","const":true},"input_url":{"description":"Websocket URL for receiving audio (null if not set)","anyOf":[{"type":"string"},{"type":"null"}]},"output_url":{"description":"Websocket URL for sending audio (null if not set)","anyOf":[{"type":"string"},{"type":"null"}]},"audio_frequency":{"description":"Audio frequency in Hz (null if not set). Supported values: 16000, 24000 (default), 32000, 48000 Hz.","anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]}},"required":["enabled","input_url","output_url","audio_frequency"]},{"type":"null"}]},"callback_config":{"description":"Callback configuration (null if callback is disabled)","anyOf":[{"type":"object","properties":{"enabled":{"type":"boolean","const":true},"url":{"description":"Callback URL","type":"string"},"secret":{"description":"Secret for validating callbacks (null if not set)","anyOf":[{"type":"string"},{"type":"null"}]},"method":{"description":"HTTP method for callback","type":"string","enum":["POST","PUT"]}},"required":["enabled","url","secret","method"]},{"type":"null"}]},"extra":{"description":"Custom metadata associated with the scheduled bot","anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]},"zoom_config":{"description":"Zoom configuration for this bot (null if not a Zoom bot or no zoom config provided)","anyOf":[{"type":"object","properties":{"credential_id":{"description":"UUID of the stored Zoom credential","anyOf":[{"type":"string","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":"null"}]},"credential_user_id":{"description":"Zoom user ID used to look up the credential","anyOf":[{"type":"string"},{"type":"null"}]},"obf_token_url":{"description":"URL that returns an OBF token at join time","anyOf":[{"type":"string"},{"type":"null"}]},"zak_token_url":{"description":"URL that returns a ZAK token at join time","anyOf":[{"type":"string"},{"type":"null"}]}}},{"type":"null"}]}},"required":["bot_id","bot_name","bot_image","meeting_url","meeting_platform","recording_mode","join_at","status","created_at","updated_at","cancelled_at","allow_multiple_bots","entry_message","timeout_config","transcription_config","streaming_config","callback_config","extra","zoom_config"]}},"required":["success","data"]},"UpdateScheduledBotResponseInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/UpdateScheduledBotResponseInput","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"object","properties":{"message":{"description":"Success message","type":"string"}},"required":["message"]}},"required":["success","data"]},"DeleteScheduledBotResponseInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/DeleteScheduledBotResponseInput","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"object","properties":{"message":{"description":"Success message","type":"string"}},"required":["message"]}},"required":["success","data"]},"ListRawCalendarsRequestBodyInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/ListRawCalendarsRequestBodyInput","type":"object","properties":{"calendar_platform":{"description":"The calendar platform to connect to. Either 'google' for Google Calendar or 'microsoft' for Microsoft Outlook/365.","type":"string","enum":["google","microsoft"]},"oauth_client_id":{"description":"Your OAuth 2.0 client ID for the calendar platform.","type":"string","minLength":1},"oauth_client_secret":{"description":"Your OAuth 2.0 client secret for the calendar platform.","type":"string","minLength":1},"oauth_refresh_token":{"description":"The OAuth 2.0 refresh token obtained from the user's authorization. Must include 'offline_access' scope (Microsoft) or 'access_type=offline' (Google).","type":"string","minLength":1},"oauth_tenant_id":{"description":"Azure AD tenant ID (required for Microsoft only, defaults to 'common'). Find it in Azure Portal > Azure Active Directory > Overview. Example: '12345678-1234-1234-1234-123456789012'. You can also use 'common', 'organizations', or 'consumers' for multi-tenant scenarios.","default":"common","type":"string"}},"required":["calendar_platform","oauth_client_id","oauth_client_secret","oauth_refresh_token"]},"CreateCalendarConnectionRequestBodyInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/CreateCalendarConnectionRequestBodyInput","type":"object","properties":{"calendar_platform":{"description":"The calendar platform to connect to. Either 'google' for Google Calendar or 'microsoft' for Microsoft Outlook/365.","type":"string","enum":["google","microsoft"]},"oauth_client_id":{"description":"Your OAuth 2.0 client ID for the calendar platform.","type":"string","minLength":1},"oauth_client_secret":{"description":"Your OAuth 2.0 client secret for the calendar platform.","type":"string","minLength":1},"oauth_refresh_token":{"description":"The OAuth 2.0 refresh token obtained from the user's authorization. Must include 'offline_access' scope (Microsoft) or 'access_type=offline' (Google).","type":"string","minLength":1},"oauth_tenant_id":{"description":"Azure AD tenant ID (required for Microsoft only, defaults to 'common'). Find it in Azure Portal > Azure Active Directory > Overview. Example: '12345678-1234-1234-1234-123456789012'. You can also use 'common', 'organizations', or 'consumers' for multi-tenant scenarios.","default":"common","type":"string"},"raw_calendar_id":{"description":"The specific calendar ID to connect. Use the 'List Raw Calendars' endpoint to get available calendar IDs. For Google, this is typically the calendar email (e.g., 'primary' or 'user@gmail.com'). For Microsoft, this is the calendar's unique identifier.","type":"string","minLength":1}},"required":["calendar_platform","oauth_client_id","oauth_client_secret","oauth_refresh_token","raw_calendar_id"]},"UpdateCalendarConnectionRequestBodyInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/UpdateCalendarConnectionRequestBodyInput","type":"object","properties":{"oauth_client_id":{"description":"Your OAuth 2.0 client ID for the calendar platform.","type":"string","minLength":1},"oauth_client_secret":{"description":"Your OAuth 2.0 client secret for the calendar platform.","type":"string","minLength":1},"oauth_refresh_token":{"description":"The OAuth 2.0 refresh token obtained from the user's authorization. Must include 'offline_access' scope (Microsoft) or 'access_type=offline' (Google).","type":"string","minLength":1},"oauth_tenant_id":{"description":"Azure AD tenant ID (required for Microsoft only, defaults to 'common'). Find it in Azure Portal > Azure Active Directory > Overview. Example: '12345678-1234-1234-1234-123456789012'. You can also use 'common', 'organizations', or 'consumers' for multi-tenant scenarios.","default":"common","type":"string"}},"required":["oauth_client_id","oauth_client_secret","oauth_refresh_token"]},"CreateCalendarBotRequestBodyInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/CreateCalendarBotRequestBodyInput","allOf":[{"type":"object","properties":{"bot_name":{"description":"The name of the bot.\n\nThis name will be displayed as the bot's name in the meeting.","example":"Meeting BaaS Bot","type":"string","minLength":1,"maxLength":255},"bot_image":{"description":"The bot's avatar image(s).\n\nAccepts a single HTTPS URL or an array of up to 5 HTTPS URLs pointing to image files (JPEG, PNG, or WebP). When multiple images are provided, they will be cycled based on the bot_image_config settings.","example":null,"default":null,"anyOf":[{"anyOf":[{"type":"string","format":"uri"},{"minItems":1,"maxItems":5,"type":"array","items":{"type":"string","format":"uri"}}]},{"type":"null"}]},"bot_image_config":{"description":"Configuration for how bot avatar images are displayed. Only relevant when multiple images are provided in bot_image.","example":null,"default":null,"anyOf":[{"type":"object","properties":{"loop_mode":{"description":"Controls how multiple bot images are cycled.\n\n- `auto`: Cycles through images at the interval specified by image_duration.\n- `bot_status`: Uses the first image when the bot joins, and the second image when recording starts. Only the first two images are used in this mode; additional images are ignored.","default":"auto","type":"string","enum":["auto","bot_status"]},"image_duration":{"description":"Duration in seconds each image is displayed before switching to the next. Only used when loop_mode is 'auto'.\n\nDefault: 30. Range: 10-120.","default":30,"type":"integer","minimum":10,"maximum":120}}},{"type":"null"}]},"recording_mode":{"description":"The recording mode of the bot.\n\nDetermines what the bot records during the meeting:\n\n- `speaker_view`: Records the speaker's view (default). Shows the active speaker or presenter.\n- `audio_only`: Records only the audio without video.\n- `gallery_view`: Records the entire gallery view (coming soon).\n\nDefault: `speaker_view`","example":"speaker_view","default":"speaker_view","type":"string","enum":["audio_only","speaker_view","gallery_view"]},"entry_message":{"description":"The message that the bot will send when it joins the meeting.\n\nThis message will be posted in the meeting chat when the bot successfully joins.\n\nAvailable for Google Meet, Microsoft Teams, and Zoom meetings.\n\nMaximum: 500 characters","example":"Hello! I'm here to record this meeting.","default":null,"anyOf":[{"type":"string","maxLength":500},{"type":"null"}]},"timeout_config":{"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.","default":{"waiting_room_timeout":600,"no_one_joined_timeout":600,"silence_timeout":600},"type":"object","properties":{"waiting_room_timeout":{"description":"The timeout in seconds for the bot to wait in the waiting room before leaving the meeting.\n\nIf the bot is placed in a waiting room and not admitted within this time, it will leave the meeting.\n\nNote: Google Meet has its own waiting room timeout (approximately 10 minutes). Setting a higher value for Google Meet meetings will have no effect, as Google Meet will deny entry to the bot after its own timeout.\n\nDefault: 600 seconds (10 minutes)\nMinimum: 2 minutes\nMaximum: 30 minutes","example":600,"default":600,"type":"integer","minimum":120,"maximum":1800},"no_one_joined_timeout":{"description":"The timeout in seconds for the bot to wait for participants to join before leaving the meeting.\n\nIf no participants join the meeting within this time after the bot joins, the bot will leave the meeting. Only applicable for Google Meet and Microsoft Teams meetings.\n\nDefault: 600 seconds (10 minutes)\nMinimum: 2 minutes\nMaximum: 30 minutes","example":600,"default":600,"type":"integer","minimum":120,"maximum":1800},"silence_timeout":{"description":"The timeout in seconds for the bot to wait for silence before leaving the meeting.\n\nIf no audio is detected for this duration after the bot joins, the bot will leave the meeting. Only applicable for Google Meet and Microsoft Teams meetings.\n\nDefault: 600 seconds (10 minutes)\nMinimum: 5 minutes\nMaximum: 30 minutes","example":600,"default":600,"type":"integer","minimum":300,"maximum":1800}}},"zoom_config":{"description":"Zoom-only configuration for authentication and join method.\n\n- **credential_id**: Use a stored Zoom credential (OBF token fetched by the bot from the API server).\n- **credential_user_id**: Resolve a stored credential by Zoom user ID.\n- **obf_token**: Provide a direct OBF token (one-off join).\n- **obf_token_url**: URL that returns an OBF token when the bot joins.\n- **zak_token_url**: URL that returns a ZAK for joining without the host.\n\nLeave `null` for Google Meet and Microsoft Teams.","example":null,"default":null,"anyOf":[{"type":"object","properties":{"credential_id":{"description":"UUID of a stored Zoom credential (created via Zoom credentials API). The bot will fetch the OBF token from the API server using this ID. Use this when you have saved a Zoom OAuth credential and want the bot to join on behalf of that user.","type":"string","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)$"},"credential_user_id":{"description":"Zoom user ID (e.g. from the Zoom profile) to look up a stored credential by user. The API server will resolve this to a credential_id. Use when you have multiple credentials and want to target a specific user.","type":"string"},"obf_token":{"description":"Direct OBF (On-Behalf-Of) token. Use this to join a Zoom meeting as a specific user without storing a credential. The token is a JWT issued by Zoom; the bot uses it once to join. Suitable for short-lived or one-off joins. For recurring use, prefer credential_id or obf_token_url.","type":"string"},"obf_token_url":{"description":"URL that returns an OBF token at join time. The bot will make a GET request with query params: bot_uuid (bot UUID) and extra (URL-encoded JSON of the run's extra payload). Use these to identify which bot/run is requesting the token. Response must be plain text (ASCII) containing the OBF token. Timeout: 15 seconds.","type":"string","format":"uri"},"zak_token_url":{"description":"URL to get the Zoom ZAK (Zoom Access Token). The bot makes a GET request with query params: bot_uuid and extra (URL-encoded JSON). Use these to identify which bot/run is requesting the token. Response must be plain text (ASCII) with the raw ZAK. See https://developers.zoom.us/docs/api/users/#tag/users/get/users/me/zak. Timeout: 15 seconds.","type":"string","format":"uri"}}},{"type":"null"}]},"extra":{"description":"An optional extra configuration object for the bot.\n\nThis object can contain any custom key-value pairs that you want to associate with the bot. The data will be:\n\n- Included in all webhook event payloads (if a webhook endpoint is configured)\n- Part of the callback payload (if callback is enabled)\n- Returned when fetching the bot's details via the API\n\nUseful for storing custom metadata, tracking information, or any other data you need to correlate with the bot.","example":null,"default":null,"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]},"streaming_enabled":{"description":"Enable audio streaming for this bot. When enabled, the streaming_config property is used to provide the configuration.","default":false,"type":"boolean"},"streaming_config":{"default":null,"anyOf":[{"example":null,"type":"object","properties":{"input_url":{"description":"Websocket stream URL, which receives the audio sent to the bot, and the bot will stream the audio to the meeting.","example":null,"default":null,"anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"output_url":{"description":"Websocket stream URL, which the bot sends the audio to. This is used to stream the output audio to a destination.","example":null,"default":null,"anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"audio_frequency":{"description":"The audio frequency in Hz. Supported values: 24000 (default), 32000, 48000 Hz.","example":null,"default":24000,"anyOf":[{"description":"Audio frequency in Hz. Supported values: 16000, 24000 (default), 32000, 48000 Hz.","anyOf":[{"type":"number","const":16000},{"type":"number","const":24000},{"type":"number","const":32000},{"type":"number","const":48000}]},{"type":"null"}]}}},{"type":"null"}]},"transcription_enabled":{"description":"Enable transcription for this bot. When enabled, the transcription_config property is used to customise the transcription provider and parameters.","default":false,"type":"boolean"},"transcription_config":{"default":null,"anyOf":[{"example":{"provider":"gladia","api_key":null,"custom_params":null},"type":"object","properties":{"provider":{"description":"The speech to text provider to use for the bot. The default and only supported provider is 'gladia'. More providers will be supported in the future.","default":"gladia","type":"string","enum":["gladia"]},"api_key":{"description":"The API key to use for the speech to text provider. This can be provided to use your own API key for the speech to text provider. It consumes less tokens than using the default API key. It is available on 'Pro' plans and above.","example":null,"default":null,"anyOf":[{"type":"string"},{"type":"null"}]},"custom_params":{"description":"Custom parameters for the transcription provider. See the transcription provider's documentation for available options. For Gladia, see https://docs.gladia.io/api-reference/v2/pre-recorded/init","example":null,"default":null,"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]}}},{"type":"null"}]},"callback_enabled":{"description":"Enable callback for this bot. When enabled, the callback_config property is used to provide the configuration.","default":false,"type":"boolean"},"callback_config":{"default":null,"anyOf":[{"example":null,"type":"object","properties":{"url":{"description":"The URL to be called upon the completion or failure of the bot.","type":"string","format":"uri"},"secret":{"description":"To ensure that you can validate the callback, this secret will be added to the request in the 'x-mb-secret' header","example":null,"default":null,"anyOf":[{"type":"string"},{"type":"null"}]},"method":{"description":"The HTTP method to use for the callback. Allowed values are 'POST' or 'PUT'.","default":"POST","type":"string","enum":["POST","PUT"]}},"required":["url"]},{"type":"null"}]}},"required":["bot_name"]},{"type":"object","properties":{"series_id":{"description":"The UUID of the event series to schedule bots for.\n\nBoth one-off and recurring events have a series_id. For recurring events, use 'all_occurrences' to schedule bots for all future occurrences.","type":"string","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)$"},"all_occurrences":{"description":"Whether to schedule bots for all occurrences of the event series.\n\nIf `true`, bots will be scheduled for all future event instances in the series. If `false`, `event_id` must be provided to schedule a bot for a specific event instance.\n\nDefault: `false`","default":false,"type":"boolean"},"event_id":{"description":"The UUID of a specific event instance to schedule a bot for.\n\nRequired when `all_occurrences` is `false`. Use this to schedule a bot for a single occurrence of a recurring event or a specific one-off event. If `all_occurrences` is `true`, this parameter is ignored.","example":null,"type":"string","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)$"}},"required":["series_id","all_occurrences"]}]},"UpdateCalendarBotRequestBodyInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/UpdateCalendarBotRequestBodyInput","allOf":[{"type":"object","properties":{"series_id":{"description":"The UUID of the event series to schedule bots for.\n\nBoth one-off and recurring events have a series_id. For recurring events, use 'all_occurrences' to schedule bots for all future occurrences.","type":"string","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)$"},"all_occurrences":{"description":"Whether to schedule bots for all occurrences of the event series.\n\nIf `true`, bots will be scheduled for all future event instances in the series. If `false`, `event_id` must be provided to schedule a bot for a specific event instance.\n\nDefault: `false`","default":false,"type":"boolean"},"event_id":{"description":"The UUID of a specific event instance to schedule a bot for.\n\nRequired when `all_occurrences` is `false`. Use this to schedule a bot for a single occurrence of a recurring event or a specific one-off event. If `all_occurrences` is `true`, this parameter is ignored.","example":null,"type":"string","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)$"}},"required":["series_id","all_occurrences"]},{"description":"Partial update of bot configuration. Only provide the fields you want to update. All fields are optional.","type":"object","properties":{"bot_name":{"description":"The name of the bot.\n\nThis name will be displayed as the bot's name in the meeting.","example":"Meeting BaaS Bot","type":"string","minLength":1,"maxLength":255},"bot_image":{"description":"The bot's avatar image(s).\n\nAccepts a single HTTPS URL or an array of up to 5 HTTPS URLs pointing to image files (JPEG, PNG, or WebP). When multiple images are provided, they will be cycled based on the bot_image_config settings.","example":null,"default":null,"anyOf":[{"anyOf":[{"type":"string","format":"uri"},{"minItems":1,"maxItems":5,"type":"array","items":{"type":"string","format":"uri"}}]},{"type":"null"}]},"bot_image_config":{"description":"Configuration for how bot avatar images are displayed. Only relevant when multiple images are provided in bot_image.","example":null,"default":null,"anyOf":[{"type":"object","properties":{"loop_mode":{"description":"Controls how multiple bot images are cycled.\n\n- `auto`: Cycles through images at the interval specified by image_duration.\n- `bot_status`: Uses the first image when the bot joins, and the second image when recording starts. Only the first two images are used in this mode; additional images are ignored.","default":"auto","type":"string","enum":["auto","bot_status"]},"image_duration":{"description":"Duration in seconds each image is displayed before switching to the next. Only used when loop_mode is 'auto'.\n\nDefault: 30. Range: 10-120.","default":30,"type":"integer","minimum":10,"maximum":120}}},{"type":"null"}]},"recording_mode":{"description":"The recording mode of the bot.\n\nDetermines what the bot records during the meeting:\n\n- `speaker_view`: Records the speaker's view (default). Shows the active speaker or presenter.\n- `audio_only`: Records only the audio without video.\n- `gallery_view`: Records the entire gallery view (coming soon).\n\nDefault: `speaker_view`","example":"speaker_view","default":"speaker_view","type":"string","enum":["audio_only","speaker_view","gallery_view"]},"entry_message":{"description":"The message that the bot will send when it joins the meeting.\n\nThis message will be posted in the meeting chat when the bot successfully joins.\n\nAvailable for Google Meet, Microsoft Teams, and Zoom meetings.\n\nMaximum: 500 characters","example":"Hello! I'm here to record this meeting.","default":null,"anyOf":[{"type":"string","maxLength":500},{"type":"null"}]},"timeout_config":{"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.","default":{"waiting_room_timeout":600,"no_one_joined_timeout":600,"silence_timeout":600},"type":"object","properties":{"waiting_room_timeout":{"description":"The timeout in seconds for the bot to wait in the waiting room before leaving the meeting.\n\nIf the bot is placed in a waiting room and not admitted within this time, it will leave the meeting.\n\nNote: Google Meet has its own waiting room timeout (approximately 10 minutes). Setting a higher value for Google Meet meetings will have no effect, as Google Meet will deny entry to the bot after its own timeout.\n\nDefault: 600 seconds (10 minutes)\nMinimum: 2 minutes\nMaximum: 30 minutes","example":600,"default":600,"type":"integer","minimum":120,"maximum":1800},"no_one_joined_timeout":{"description":"The timeout in seconds for the bot to wait for participants to join before leaving the meeting.\n\nIf no participants join the meeting within this time after the bot joins, the bot will leave the meeting. Only applicable for Google Meet and Microsoft Teams meetings.\n\nDefault: 600 seconds (10 minutes)\nMinimum: 2 minutes\nMaximum: 30 minutes","example":600,"default":600,"type":"integer","minimum":120,"maximum":1800},"silence_timeout":{"description":"The timeout in seconds for the bot to wait for silence before leaving the meeting.\n\nIf no audio is detected for this duration after the bot joins, the bot will leave the meeting. Only applicable for Google Meet and Microsoft Teams meetings.\n\nDefault: 600 seconds (10 minutes)\nMinimum: 5 minutes\nMaximum: 30 minutes","example":600,"default":600,"type":"integer","minimum":300,"maximum":1800}}},"zoom_config":{"description":"Zoom-only configuration for authentication and join method.\n\n- **credential_id**: Use a stored Zoom credential (OBF token fetched by the bot from the API server).\n- **credential_user_id**: Resolve a stored credential by Zoom user ID.\n- **obf_token**: Provide a direct OBF token (one-off join).\n- **obf_token_url**: URL that returns an OBF token when the bot joins.\n- **zak_token_url**: URL that returns a ZAK for joining without the host.\n\nLeave `null` for Google Meet and Microsoft Teams.","example":null,"default":null,"anyOf":[{"type":"object","properties":{"credential_id":{"description":"UUID of a stored Zoom credential (created via Zoom credentials API). The bot will fetch the OBF token from the API server using this ID. Use this when you have saved a Zoom OAuth credential and want the bot to join on behalf of that user.","type":"string","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)$"},"credential_user_id":{"description":"Zoom user ID (e.g. from the Zoom profile) to look up a stored credential by user. The API server will resolve this to a credential_id. Use when you have multiple credentials and want to target a specific user.","type":"string"},"obf_token":{"description":"Direct OBF (On-Behalf-Of) token. Use this to join a Zoom meeting as a specific user without storing a credential. The token is a JWT issued by Zoom; the bot uses it once to join. Suitable for short-lived or one-off joins. For recurring use, prefer credential_id or obf_token_url.","type":"string"},"obf_token_url":{"description":"URL that returns an OBF token at join time. The bot will make a GET request with query params: bot_uuid (bot UUID) and extra (URL-encoded JSON of the run's extra payload). Use these to identify which bot/run is requesting the token. Response must be plain text (ASCII) containing the OBF token. Timeout: 15 seconds.","type":"string","format":"uri"},"zak_token_url":{"description":"URL to get the Zoom ZAK (Zoom Access Token). The bot makes a GET request with query params: bot_uuid and extra (URL-encoded JSON). Use these to identify which bot/run is requesting the token. Response must be plain text (ASCII) with the raw ZAK. See https://developers.zoom.us/docs/api/users/#tag/users/get/users/me/zak. Timeout: 15 seconds.","type":"string","format":"uri"}}},{"type":"null"}]},"extra":{"description":"An optional extra configuration object for the bot.\n\nThis object can contain any custom key-value pairs that you want to associate with the bot. The data will be:\n\n- Included in all webhook event payloads (if a webhook endpoint is configured)\n- Part of the callback payload (if callback is enabled)\n- Returned when fetching the bot's details via the API\n\nUseful for storing custom metadata, tracking information, or any other data you need to correlate with the bot.","example":null,"default":null,"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]},"streaming_enabled":{"description":"Enable or disable audio streaming for this bot.\n\n- Set to `true` to enable streaming (requires `streaming_config`)\n- Set to `false` to disable streaming (do not provide `streaming_config`)\n- Omit this field to leave streaming configuration unchanged\n\nIf you want to change streaming settings, you must provide both `streaming_enabled` and `streaming_config` together.","type":"boolean"},"streaming_config":{"description":"The streaming configuration for the bot.\n\nRequired when `streaming_enabled` is `true`. Must not be provided when `streaming_enabled` is `false`.\n\n- `input_url`: Websocket stream URL that receives audio sent to the bot\n- `output_url`: Websocket stream URL where the bot sends audio\n- `audio_frequency`: Audio frequency in Hz (default: 24000)\n\nOmit this field to leave streaming configuration unchanged.","example":null,"type":"object","properties":{"input_url":{"description":"Websocket stream URL, which receives the audio sent to the bot, and the bot will stream the audio to the meeting.","example":null,"default":null,"anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"output_url":{"description":"Websocket stream URL, which the bot sends the audio to. This is used to stream the output audio to a destination.","example":null,"default":null,"anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"audio_frequency":{"description":"The audio frequency in Hz. Supported values: 24000 (default), 32000, 48000 Hz.","example":null,"default":24000,"anyOf":[{"description":"Audio frequency in Hz. Supported values: 16000, 24000 (default), 32000, 48000 Hz.","anyOf":[{"type":"number","const":16000},{"type":"number","const":24000},{"type":"number","const":32000},{"type":"number","const":48000}]},{"type":"null"}]}}},"transcription_enabled":{"description":"Enable or disable transcription for this bot.\n\n- Set to `true` to enable transcription (requires `transcription_config`)\n- Set to `false` to disable transcription (do not provide `transcription_config`)\n- Omit this field to leave transcription configuration unchanged\n\nIf you want to change transcription settings, you must provide both `transcription_enabled` and `transcription_config` together.","type":"boolean"},"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\")\n- `api_key`: Your own API key for the provider (BYOK - available on Pro plans and above)\n- `custom_params`: Custom parameters for transcription (see Gladia API documentation)\n\nOmit this field to leave transcription configuration unchanged.","example":{"provider":"gladia","api_key":null,"custom_params":null},"type":"object","properties":{"provider":{"description":"The speech to text provider to use for the bot. The default and only supported provider is 'gladia'. More providers will be supported in the future.","default":"gladia","type":"string","enum":["gladia"]},"api_key":{"description":"The API key to use for the speech to text provider. This can be provided to use your own API key for the speech to text provider. It consumes less tokens than using the default API key. It is available on 'Pro' plans and above.","example":null,"default":null,"anyOf":[{"type":"string"},{"type":"null"}]},"custom_params":{"description":"Custom parameters for the transcription provider. See the transcription provider's documentation for available options. For Gladia, see https://docs.gladia.io/api-reference/v2/pre-recorded/init","example":null,"default":null,"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]}}},"callback_enabled":{"description":"Enable or disable callback for this bot.\n\n- Set to `true` to enable callback (requires `callback_config`)\n- Set to `false` to disable callback (do not provide `callback_config`)\n- Omit this field to leave callback configuration unchanged\n\nIf you want to change callback settings, you must provide both `callback_enabled` and `callback_config` together.","type":"boolean"},"callback_config":{"description":"The callback configuration for the bot.\n\nRequired when `callback_enabled` is `true`. Must not be provided when `callback_enabled` is `false`.\n\n- `url`: The URL to be called upon completion or failure of the bot\n- `secret`: Secret for HMAC validation (sent in `x-mb-secret` header)\n- `method`: HTTP method (`POST` or `PUT`, default: `POST`)\n\nOmit this field to leave callback configuration unchanged.","example":null,"type":"object","properties":{"url":{"description":"The URL to be called upon the completion or failure of the bot.","type":"string","format":"uri"},"secret":{"description":"To ensure that you can validate the callback, this secret will be added to the request in the 'x-mb-secret' header","example":null,"default":null,"anyOf":[{"type":"string"},{"type":"null"}]},"method":{"description":"The HTTP method to use for the callback. Allowed values are 'POST' or 'PUT'.","default":"POST","type":"string","enum":["POST","PUT"]}},"required":["url"]}}}]},"ListRawCalendarsResponseInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/ListRawCalendarsResponseInput","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"array","items":{"type":"object","properties":{"id":{"description":"The calendar ID from the calendar platform. Use this value as the 'raw_calendar_id' parameter when creating a calendar connection","type":"string"},"name":{"description":"The display name of the calendar as shown in the calendar application","type":"string"},"email":{"description":"The email address associated with the calendar. For Google Calendar, this is typically the calendar owner's email. For Microsoft, this is the calendar's email address","type":"string"},"is_primary":{"description":"Whether this is the user's primary/default calendar. The primary calendar is typically the main calendar associated with the user's account","type":"boolean"}},"required":["id","name","email","is_primary"]}}},"required":["success","data"]},"CreateCalendarConnectionResponseInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/CreateCalendarConnectionResponseInput","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"object","properties":{"calendar_id":{"description":"The UUID of the newly created calendar connection. Use this ID to reference the calendar in other API endpoints","type":"string","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)$"},"calendar_platform":{"description":"The calendar platform where this connection was established. Either 'google' for Google Calendar or 'microsoft' for Microsoft Outlook/365","type":"string","enum":["google","microsoft"]},"account_email":{"description":"The email address associated with the calendar account. This is the email of the calendar owner","type":"string"},"status":{"description":"The current status of the calendar connection. Possible values: 'active' (connection is working), 'error' (connection has errors), 'revoked' (OAuth access was revoked), 'permission_denied' (insufficient permissions)","type":"string","enum":["active","error","revoked","permission_denied"]},"created_at":{"description":"ISO 8601 timestamp when the calendar connection was created and synced","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["calendar_id","calendar_platform","account_email","status","created_at"]}},"required":["success","data"]},"ListCalendarsResponseInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/ListCalendarsResponseInput","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"array","items":{"type":"object","properties":{"calendar_id":{"description":"The UUID of the calendar connection. Use this ID to reference the calendar in other API endpoints","type":"string","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)$"},"calendar_platform":{"description":"The calendar platform. Either 'google' for Google Calendar or 'microsoft' for Microsoft Outlook/365","type":"string","enum":["google","microsoft"]},"account_email":{"description":"The email address associated with the calendar account. This is the email of the calendar owner","type":"string"},"status":{"description":"The current status of the calendar connection. Possible values: 'active' (connection is working), 'error' (connection has errors), 'revoked' (OAuth access was revoked), 'permission_denied' (insufficient permissions)","type":"string","enum":["active","error","revoked","permission_denied"]},"synced_at":{"description":"ISO 8601 timestamp of the last successful calendar sync. Null if the calendar has never been synced yet. Syncs happen automatically when events change, or can be triggered manually using the sync endpoint","anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"created_at":{"description":"ISO 8601 timestamp when the calendar connection was created and initially synced","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["calendar_id","calendar_platform","account_email","status","synced_at","created_at"]}},"cursor":{"description":"Cursor for the next page (null if no more pages)","anyOf":[{"type":"string"},{"type":"null"}]},"prev_cursor":{"description":"Cursor for the previous page (null if on first page)","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["success","data","cursor","prev_cursor"]},"GetCalendarDetailsResponseInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/GetCalendarDetailsResponseInput","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"object","properties":{"calendar_id":{"description":"The UUID of the calendar connection. Use this ID to reference the calendar in other API endpoints","type":"string","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)$"},"calendar_platform":{"description":"The calendar platform. Either 'google' for Google Calendar or 'microsoft' for Microsoft Outlook/365","type":"string","enum":["google","microsoft"]},"account_email":{"description":"The email address associated with the calendar account. This is the email of the calendar owner","type":"string"},"status":{"description":"The current status of the calendar connection. Possible values: 'active' (connection is working), 'error' (connection has errors), 'revoked' (OAuth access was revoked), 'permission_denied' (insufficient permissions)","type":"string","enum":["active","error","revoked","permission_denied"]},"status_message":{"description":"A human-readable message providing additional context about the connection status. Null if there is no additional status message to display","anyOf":[{"type":"string"},{"type":"null"}]},"subscription_id":{"description":"The subscription ID assigned by the calendar provider (Google or Microsoft). This ID is used to manage the webhook subscription. Null if no subscription exists","anyOf":[{"type":"string"},{"type":"null"}]},"subscription_expires_at":{"description":"ISO 8601 timestamp when the webhook subscription expires. Subscriptions typically expire after a certain period (e.g., 7 days for Google, 3 days for Microsoft) and need to be renewed. Null if no subscription exists","anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"synced_at":{"description":"ISO 8601 timestamp of the last successful calendar sync. Null if the calendar has never been synced. Syncs fetch events from the calendar platform and update the local database","anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"sync_status":{"description":"The status of the last sync operation. Null if no sync has been performed yet. Possible values when not null: 'success' (sync completed successfully), 'failed' (sync failed completely), 'partial' (sync completed but some events could not be processed)","anyOf":[{"type":"string","enum":["success","failed","partial"]},{"type":"null"}]},"sync_error":{"description":"Error message from the last sync operation if it failed. This provides details about what went wrong during the sync. Null if the last sync was successful or if no sync has been performed","anyOf":[{"type":"string"},{"type":"null"}]},"provider_metadata":{"description":"Additional metadata returned by the calendar provider about this calendar. This may include calendar-specific settings, permissions, or other platform-specific information. Null if the provider did not return metadata or if metadata is not available","anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]},"created_at":{"description":"ISO 8601 timestamp when the calendar connection was created and initially synced","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"updated_at":{"description":"ISO 8601 timestamp when the calendar connection was last updated. This updates when connection settings change, credentials are refreshed, or subscription details are updated","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["calendar_id","calendar_platform","account_email","status","status_message","subscription_id","subscription_expires_at","synced_at","sync_status","sync_error","provider_metadata","created_at","updated_at"]}},"required":["success","data"]},"UpdateCalendarConnectionResponseInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/UpdateCalendarConnectionResponseInput","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"object","properties":{"calendar_id":{"description":"The UUID of the updated calendar connection. Use this ID to reference the calendar in other API endpoints","type":"string","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)$"},"calendar_platform":{"description":"The calendar platform. Either 'google' for Google Calendar or 'microsoft' for Microsoft Outlook/365","type":"string","enum":["google","microsoft"]},"account_email":{"description":"The email address associated with the calendar account. This is the email of the calendar owner","type":"string"},"status":{"description":"The current status of the calendar connection after the update. Possible values: 'active' (connection is working), 'error' (connection has errors), 'revoked' (OAuth access was revoked), 'permission_denied' (insufficient permissions)","type":"string","enum":["active","error","revoked","permission_denied"]},"updated_at":{"description":"ISO 8601 timestamp when the calendar connection was last updated with the new credentials or settings","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["calendar_id","calendar_platform","account_email","status","updated_at"]}},"required":["success","data"]},"DeleteCalendarConnectionResponseInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/DeleteCalendarConnectionResponseInput","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"object","properties":{"message":{"description":"Success message confirming that the calendar connection has been deleted. All associated event instances, series, and bot schedules have also been removed","type":"string"}},"required":["message"]}},"required":["success","data"]},"SyncCalendarResponseInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/SyncCalendarResponseInput","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"object","properties":{"message":{"description":"Success message confirming that the calendar sync operation has been initiated. The sync will fetch the latest events from the calendar platform and update the local database","type":"string"}},"required":["message"]}},"required":["success","data"]},"ResubscribeCalendarResponseInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/ResubscribeCalendarResponseInput","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"object","properties":{"calendar_id":{"description":"The UUID of the calendar connection that was resubscribed. Use this ID to reference the calendar in other API endpoints","type":"string","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)$"},"resubscribed_at":{"description":"ISO 8601 timestamp when the calendar connection was resubscribed","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["calendar_id","resubscribed_at"]}},"required":["success","data"]},"ListEventsResponseInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/ListEventsResponseInput","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"array","items":{"type":"object","properties":{"series_id":{"description":"The UUID of the event series this instance belongs to. Every event instance (both one-off and recurring) is associated with a series. Use this ID when scheduling bots for all occurrences of a recurring series","type":"string","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)$"},"event_type":{"description":"The type of event. 'one_off' for single events that occur once, 'recurring' for events that are part of a recurring series with multiple occurrences","type":"string","enum":["one_off","recurring"]},"event_id":{"description":"The UUID of the event instance","type":"string","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)$"},"title":{"description":"The title of the event","type":"string"},"start_time":{"description":"ISO 8601 timestamp when the event starts","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"end_time":{"description":"ISO 8601 timestamp when the event ends","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"status":{"description":"The status of the event. Possible values: 'confirmed' (event is confirmed), 'cancelled' (event has been cancelled), 'tentative' (event is tentative)","type":"string","enum":["confirmed","cancelled","tentative"]},"is_exception":{"description":"Whether this is an exception to a recurring series. True if this instance has been modified differently from the recurring pattern","type":"boolean"},"meeting_url":{"description":"The meeting URL extracted from the event. Null if the calendar platform did not include a meeting link in the event","anyOf":[{"type":"string"},{"type":"null"}]},"meeting_platform":{"description":"The meeting platform detected from the meeting URL. Null if no meeting link was found in the event. Possible values: 'zoom', 'meet', or 'teams'","anyOf":[{"type":"string","enum":["zoom","meet","teams"]},{"type":"null"}]},"calendar_id":{"description":"The UUID of the calendar connection this event belongs to","type":"string","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)$"},"bot_scheduled":{"description":"Whether a bot has been scheduled for this event instance. True if a calendar bot schedule exists for this event","type":"boolean"},"created_at":{"description":"ISO 8601 timestamp when this event instance was first synced into the system","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["series_id","event_type","event_id","title","start_time","end_time","status","is_exception","meeting_url","meeting_platform","calendar_id","bot_scheduled","created_at"]}},"cursor":{"description":"Cursor for the next page (null if no more pages)","anyOf":[{"type":"string"},{"type":"null"}]},"prev_cursor":{"description":"Cursor for the previous page (null if on first page)","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["success","data","cursor","prev_cursor"]},"ListEventSeriesResponseInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/ListEventSeriesResponseInput","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"array","items":{"type":"object","properties":{"series_id":{"description":"The UUID of the event series. Every event (both one-off and recurring) is associated with a series. Use this ID when scheduling bots for all occurrences of a recurring series","type":"string","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)$"},"event_type":{"description":"The type of event. 'one_off' for single events that occur once, 'recurring' for events that are part of a recurring series with multiple occurrences","type":"string","enum":["one_off","recurring"]},"calendar_id":{"description":"The UUID of the calendar connection this event series belongs to","type":"string","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)$"},"created_at":{"description":"ISO 8601 timestamp when this event series was first synced into the system","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"events":{"description":"List of event instances that belong to this series. For one-off events, this array contains a single instance. For recurring events, this array contains all instances that have been synced (typically within a 30-day window)","type":"array","items":{"type":"object","properties":{"event_id":{"description":"The UUID of the event instance","type":"string","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)$"},"title":{"description":"The title of the event","type":"string"},"start_time":{"description":"ISO 8601 timestamp when the event starts","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"end_time":{"description":"ISO 8601 timestamp when the event ends","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"status":{"description":"The status of the event. Possible values: 'confirmed' (event is confirmed), 'cancelled' (event has been cancelled), 'tentative' (event is tentative)","type":"string","enum":["confirmed","cancelled","tentative"]},"is_exception":{"description":"Whether this is an exception to a recurring series. True if this instance has been modified differently from the recurring pattern","type":"boolean"},"meeting_url":{"description":"The meeting URL extracted from the event. Null if the calendar platform did not include a meeting link in the event","anyOf":[{"type":"string"},{"type":"null"}]},"meeting_platform":{"description":"The meeting platform detected from the meeting URL. Null if no meeting link was found in the event. Possible values: 'zoom', 'meet', or 'teams'","anyOf":[{"type":"string","enum":["zoom","meet","teams"]},{"type":"null"}]},"calendar_id":{"description":"The UUID of the calendar connection this event belongs to","type":"string","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)$"},"bot_scheduled":{"description":"Whether a bot has been scheduled for this event instance. True if a calendar bot schedule exists for this event","type":"boolean"},"created_at":{"description":"ISO 8601 timestamp when this event instance was first synced into the system","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["event_id","title","start_time","end_time","status","is_exception","meeting_url","meeting_platform","calendar_id","bot_scheduled","created_at"]}}},"required":["series_id","event_type","calendar_id","created_at","events"]}},"cursor":{"description":"Cursor for the next page (null if no more pages)","anyOf":[{"type":"string"},{"type":"null"}]},"prev_cursor":{"description":"Cursor for the previous page (null if on first page)","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["success","data","cursor","prev_cursor"]},"GetEventDetailsResponseInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/GetEventDetailsResponseInput","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"object","properties":{"event_id":{"description":"The UUID of the event instance","type":"string","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)$"},"series_id":{"description":"The UUID of the event series this instance belongs to. Every event instance (both one-off and recurring) is associated with a series. Use this ID when scheduling bots for all occurrences of a recurring series","type":"string","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)$"},"event_type":{"description":"The type of event. 'one_off' for single events that occur once, 'recurring' for events that are part of a recurring series with multiple occurrences","type":"string","enum":["one_off","recurring"]},"title":{"description":"The title of the event as stored in the calendar","type":"string"},"description":{"description":"The description of the event as returned by the calendar platform. Null if the calendar platform did not include a description for this event","anyOf":[{"type":"string"},{"type":"null"}]},"location":{"description":"The location of the event as returned by the calendar platform. Null if the calendar platform did not include a location for this event","anyOf":[{"type":"string"},{"type":"null"}]},"start_time":{"description":"ISO 8601 timestamp when the event starts","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"end_time":{"description":"ISO 8601 timestamp when the event ends","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"timezone":{"description":"The IANA timezone identifier for the event (e.g., 'America/New_York', 'Europe/London'). Null if the calendar platform did not provide timezone information or if the event is all-day","anyOf":[{"type":"string"},{"type":"null"}]},"is_all_day":{"description":"Whether this is an all-day event. True if the event spans entire days without specific start/end times","type":"boolean"},"status":{"description":"The status of the event. Possible values: 'confirmed' (event is confirmed), 'cancelled' (event has been cancelled), 'tentative' (event is tentative)","type":"string","enum":["confirmed","cancelled","tentative"]},"organizer_email":{"description":"The email address of the event organizer as returned by the calendar platform. Null if the calendar platform did not provide organizer information","anyOf":[{"type":"string"},{"type":"null"}]},"organizer_name":{"description":"The display name of the event organizer as returned by the calendar platform. Null if the calendar platform did not provide organizer name information","anyOf":[{"type":"string"},{"type":"null"}]},"attendees":{"description":"List of event attendees as returned by the calendar platform. Null if the calendar platform did not provide attendee information or if the event has no attendees","anyOf":[{"type":"array","items":{"type":"object","properties":{"email":{"description":"The email address of the attendee","type":"string"},"name":{"description":"The display name of the attendee as returned by the calendar platform. Null if the calendar platform did not provide a display name for this attendee","anyOf":[{"type":"string"},{"type":"null"}]},"response_status":{"description":"The attendee's response status to the event invitation. Defaults to 'needsAction' if the calendar platform did not provide response status information. Possible values: 'accepted' (attendee accepted the invitation), 'declined' (attendee declined the invitation), 'tentative' (attendee responded as tentative), 'needsAction' (attendee has not responded yet)","type":"string","enum":["accepted","declined","tentative","needsAction"]},"organizer":{"description":"Whether this attendee is the organizer of the event. Only present if the calendar platform provides this information","type":"boolean"},"self":{"description":"Whether this attendee represents the authenticated user who owns the calendar connection. Only present if the calendar platform provides this information","type":"boolean"}},"required":["email","name","response_status"]}},{"type":"null"}]},"meeting_url":{"description":"The meeting URL extracted from the event. Null if the calendar platform did not include a meeting link in the event","anyOf":[{"type":"string"},{"type":"null"}]},"meeting_platform":{"description":"The meeting platform detected from the meeting URL. Null if no meeting link was found in the event. Possible values: 'zoom', 'meet', or 'teams'","anyOf":[{"type":"string","enum":["zoom","meet","teams"]},{"type":"null"}]},"calendar_id":{"description":"The UUID of the calendar connection this event belongs to","type":"string","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)$"},"calendar_platform":{"description":"The calendar platform where this event originates. Either 'google' for Google Calendar or 'microsoft' for Microsoft Outlook/365","type":"string","enum":["google","microsoft"]},"bot_scheduled":{"description":"Whether a bot has been scheduled for this event instance. True if a calendar bot schedule exists for this event","type":"boolean"},"created_at":{"description":"ISO 8601 timestamp when this event instance was first synced into the system","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"updated_at":{"description":"ISO 8601 timestamp when this event instance was last updated (either from a sync or from a webhook notification)","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["event_id","series_id","event_type","title","description","location","start_time","end_time","timezone","is_all_day","status","organizer_email","organizer_name","attendees","meeting_url","meeting_platform","calendar_id","calendar_platform","bot_scheduled","created_at","updated_at"]}},"required":["success","data"]},"CreateCalendarBotResponseInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/CreateCalendarBotResponseInput","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"description":"Event instances that were successfully scheduled for bot recording or had their bots updated/deleted successfully","type":"array","items":{"type":"object","properties":{"event_id":{"description":"The UUID of the event instance that was successfully scheduled for bot recording","type":"string","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)$"}},"required":["event_id"]}},"errors":{"description":"Array of errors for event instances that failed to schedule. This array is empty if all event instances were successfully scheduled. Each error object contains information about a specific event instance that could not be scheduled","type":"array","items":{"type":"object","properties":{"event_id":{"description":"The UUID of the event instance that failed to be scheduled. Use this to identify which specific event could not be scheduled","type":"string","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)$"},"code":{"description":"Error code for programmatic handling. This is a machine-readable identifier that indicates the type of error that occurred","type":"string"},"message":{"description":"Human-readable error message explaining why the scheduling failed for this event instance","type":"string"},"details":{"description":"Additional error details providing more context about the failure. Null if no additional details are available","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["event_id","code","message","details"]}}},"required":["success","data","errors"]},"UpdateCalendarBotResponseInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/UpdateCalendarBotResponseInput","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"description":"Event instances whose calendar bots were successfully updated","type":"array","items":{"type":"object","properties":{"event_id":{"description":"The UUID of the event instance that was successfully scheduled for bot recording","type":"string","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)$"}},"required":["event_id"]}},"errors":{"description":"Array of errors for event instances whose calendar bots could not be updated. This array is empty if all requested event instances were successfully updated","type":"array","items":{"type":"object","properties":{"event_id":{"description":"The UUID of the event instance that failed to be scheduled. Use this to identify which specific event could not be scheduled","type":"string","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)$"},"code":{"description":"Error code for programmatic handling. This is a machine-readable identifier that indicates the type of error that occurred","type":"string"},"message":{"description":"Human-readable error message explaining why the scheduling failed for this event instance","type":"string"},"details":{"description":"Additional error details providing more context about the failure. Null if no additional details are available","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["event_id","code","message","details"]}}},"required":["success","data","errors"]},"DeleteCalendarBotResponseInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/DeleteCalendarBotResponseInput","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"description":"Event instances whose calendar bots were successfully deleted/cancelled","type":"array","items":{"type":"object","properties":{"event_id":{"description":"The UUID of the event instance that was successfully scheduled for bot recording","type":"string","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)$"}},"required":["event_id"]}},"errors":{"description":"Array of errors for event instances whose calendar bots could not be deleted. This array is empty if all requested event instances were successfully deleted","type":"array","items":{"type":"object","properties":{"event_id":{"description":"The UUID of the event instance that failed to be scheduled. Use this to identify which specific event could not be scheduled","type":"string","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)$"},"code":{"description":"Error code for programmatic handling. This is a machine-readable identifier that indicates the type of error that occurred","type":"string"},"message":{"description":"Human-readable error message explaining why the scheduling failed for this event instance","type":"string"},"details":{"description":"Additional error details providing more context about the failure. Null if no additional details are available","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["event_id","code","message","details"]}}},"required":["success","data","errors"]},"BotWebhookStatusChangeInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/BotWebhookStatusChangeInput","type":"object","properties":{"event":{"description":"The webhook event type","type":"string","const":"bot.status_change"},"data":{"type":"object","properties":{"bot_id":{"description":"The UUID of the bot that changed status","type":"string","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)$"},"event_id":{"description":"The UUID of the calendar event associated with this bot. Null for non-calendar bots","anyOf":[{"type":"string","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":"null"}]},"status":{"description":"Status information with code, timestamp, and optional status-specific fields","type":"object","properties":{"code":{"description":"The status code (e.g., 'transcribing', 'recording', 'processing')","type":"string"},"created_at":{"description":"ISO 8601 timestamp when this status change occurred","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"start_time":{"description":"Unix timestamp (seconds) when recording started. Only present for 'in_call_recording' status","type":"integer","minimum":0,"maximum":9007199254740991},"error_message":{"description":"Error message describing what went wrong. Only present for 'recording_failed' status","type":"string"}},"required":["code","created_at"]}},"required":["bot_id","event_id","status"]},"extra":{"description":"Additional metadata provided when creating the bot. This is user-defined data that can be used for correlation or tracking","anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]}},"required":["event","data","extra"]},"BotWebhookCompletedInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/CallbackCompletedInput","type":"object","properties":{"event":{"description":"The webhook event type","type":"string","const":"bot.completed"},"data":{"type":"object","properties":{"bot_id":{"description":"The UUID of the bot that completed","type":"string","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)$"},"event_id":{"description":"The UUID of the calendar event associated with this bot. Null for non-calendar bots","anyOf":[{"type":"string","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":"null"}]},"participants":{"description":"List of participants who joined the meeting with their names and metadata. Empty array if participant information is not available","type":"array","items":{"type":"object","properties":{"name":{"description":"Participant's name (full name or display name)","type":"string"},"id":{"description":"Sequential participant ID (1, 2, 3...). Null if not available","anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"display_name":{"description":"Display name shown in UI (if different from name)","type":"string"},"profile_picture":{"description":"Profile picture URL (if available)","type":"string","format":"uri"}},"required":["name","id"]}},"speakers":{"description":"List of speakers detected in the meeting with their names and metadata. Empty array if speaker information is not available","type":"array","items":{"type":"object","properties":{"name":{"description":"Participant's name (full name or display name)","type":"string"},"id":{"description":"Sequential participant ID (1, 2, 3...). Null if not available","anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"display_name":{"description":"Display name shown in UI (if different from name)","type":"string"},"profile_picture":{"description":"Profile picture URL (if available)","type":"string","format":"uri"}},"required":["name","id"]}},"duration_seconds":{"anyOf":[{"description":"The duration of the meeting in seconds. Null if duration could not be determined","type":"integer","minimum":0,"maximum":9007199254740991},{"type":"null"}]},"joined_at":{"description":"ISO 8601 timestamp when the bot joined the meeting. Null if join time is not available","anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"exited_at":{"description":"ISO 8601 timestamp when the bot exited the meeting. Null if exit time is not available","anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"data_deleted":{"description":"Whether the bot's data (artifacts, recordings) has been deleted. True if data has been permanently removed","type":"boolean"},"video":{"description":"Signed URL to download the video recording. Valid for 4 hours. Null if video recording is not available or has been deleted","anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"audio":{"description":"Signed URL to download the audio recording. Valid for 4 hours. Null if audio recording is not available or has been deleted","anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"diarization":{"description":"Signed URL to download the speaker diarization data. Valid for 4 hours. Null if diarization is not available or has been deleted","anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"raw_transcription":{"description":"Signed URL to download the raw transcription file. Valid for 4 hours. Null if raw transcription is not available or has been deleted","anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"transcription":{"description":"Signed URL to download the processed transcription file. Valid for 4 hours. Null if transcription is not available or has been deleted","anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"transcription_provider":{"description":"The transcription provider used (e.g., 'gladia'). Null if transcription was not enabled or if provider information is not available","anyOf":[{"type":"string"},{"type":"null"}]},"transcription_ids":{"description":"Array of transcription job IDs from the transcription provider. Null if transcription was not enabled or if IDs are not available","anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}]},"sent_at":{"description":"ISO 8601 timestamp when this webhook was sent","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["bot_id","event_id","participants","speakers","duration_seconds","joined_at","exited_at","data_deleted","video","audio","diarization","raw_transcription","transcription","transcription_provider","transcription_ids","sent_at"]},"extra":{"description":"Additional metadata provided when creating the bot. This is user-defined data that can be used for correlation or tracking","anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]}},"required":["event","data","extra"]},"BotWebhookFailedInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/CallbackFailedInput","type":"object","properties":{"event":{"description":"The webhook event type","type":"string","const":"bot.failed"},"data":{"type":"object","properties":{"bot_id":{"description":"The UUID of the bot that failed","type":"string","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)$"},"event_id":{"description":"The UUID of the calendar event associated with this bot. Null for non-calendar bots","anyOf":[{"type":"string","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":"null"}]},"error_message":{"description":"Human-readable error message describing why the bot failed","type":"string"},"error_code":{"description":"Machine-readable error code for programmatic handling. Common codes include 'MEETING_NOT_FOUND', 'MEETING_ENDED', 'BOT_CRASHED', etc.","type":"string"},"sent_at":{"description":"ISO 8601 timestamp when this webhook was sent","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["bot_id","event_id","error_message","error_code","sent_at"]},"extra":{"description":"Additional metadata provided when creating the bot. This is user-defined data that can be used for correlation or tracking","anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]}},"required":["event","data","extra"]},"BotWebhookChatMessageInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/BotWebhookChatMessageInput","type":"object","properties":{"event":{"description":"The webhook event type","type":"string","const":"bot.chat_message"},"data":{"type":"object","properties":{"bot_id":{"description":"The UUID of the bot that received the chat message","type":"string","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)$"},"event_id":{"description":"The UUID of the calendar event associated with this bot. Null for non-calendar bots","anyOf":[{"type":"string","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":"null"}]},"message_id":{"description":"Unique identifier of the chat message","type":"string"},"sender_name":{"description":"Display name of the message sender","type":"string"},"sender_id":{"description":"Sequential participant ID of the sender. Null if the sender could not be resolved to a participant","anyOf":[{"type":"integer","minimum":0,"maximum":9007199254740991},{"type":"null"}]},"text":{"description":"Text content of the chat message","type":"string"},"sent_at":{"description":"ISO 8601 timestamp when this webhook was sent","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["bot_id","event_id","message_id","sender_name","sender_id","text","sent_at"]},"extra":{"description":"Additional metadata provided when creating the bot. This is user-defined data that can be used for correlation or tracking","anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]}},"required":["event","data","extra"]},"CalendarWebhookConnectionCreatedInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/CalendarWebhookConnectionCreatedInput","type":"object","properties":{"event":{"description":"The webhook event type","type":"string","const":"calendar.connection_created"},"data":{"type":"object","properties":{"calendar_id":{"description":"The UUID of the newly created calendar connection","type":"string","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)$"},"calendar_platform":{"description":"The calendar platform. Either 'google' for Google Calendar or 'microsoft' for Microsoft Outlook/365","type":"string","enum":["google","microsoft"]},"account_email":{"description":"The email address associated with the calendar account","type":"string"},"status":{"description":"The current status of the calendar connection. Possible values: 'active' (connection is working), 'error' (connection has errors), 'revoked' (OAuth access was revoked), 'permission_denied' (insufficient permissions)","type":"string","enum":["active","error","revoked","permission_denied"]},"created_at":{"description":"ISO 8601 timestamp when the calendar connection was created","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["calendar_id","calendar_platform","account_email","status","created_at"]}},"required":["event","data"]},"CalendarWebhookConnectionUpdatedInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/CalendarWebhookConnectionUpdatedInput","type":"object","properties":{"event":{"description":"The webhook event type","type":"string","const":"calendar.connection_updated"},"data":{"type":"object","properties":{"calendar_id":{"description":"The UUID of the updated calendar connection","type":"string","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)$"},"calendar_platform":{"description":"The calendar platform. Either 'google' for Google Calendar or 'microsoft' for Microsoft Outlook/365","type":"string","enum":["google","microsoft"]},"account_email":{"description":"The email address associated with the calendar account","type":"string"},"status":{"description":"The current status of the calendar connection after the update. Possible values: 'active' (connection is working), 'error' (connection has errors), 'revoked' (OAuth access was revoked), 'permission_denied' (insufficient permissions)","type":"string","enum":["active","error","revoked","permission_denied"]},"created_at":{"description":"ISO 8601 timestamp when the calendar connection was originally created","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"updated_at":{"description":"ISO 8601 timestamp when the calendar connection was updated","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["calendar_id","calendar_platform","account_email","status","created_at","updated_at"]}},"required":["event","data"]},"CalendarWebhookConnectionDeletedInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/CalendarWebhookConnectionDeletedInput","type":"object","properties":{"event":{"description":"The webhook event type","type":"string","const":"calendar.connection_deleted"},"data":{"type":"object","properties":{"calendar_id":{"description":"The UUID of the deleted calendar connection","type":"string","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)$"},"calendar_platform":{"description":"The calendar platform. Either 'google' for Google Calendar or 'microsoft' for Microsoft Outlook/365","type":"string","enum":["google","microsoft"]},"deleted_at":{"description":"ISO 8601 timestamp when the calendar connection was deleted","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["calendar_id","calendar_platform","deleted_at"]}},"required":["event","data"]},"CalendarWebhookEventsSyncedInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/CalendarWebhookEventsSyncedInput","type":"object","properties":{"event":{"description":"The webhook event type","type":"string","const":"calendar.events_synced"},"data":{"type":"object","properties":{"calendar_id":{"description":"The UUID of the calendar connection that was synced","type":"string","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)$"},"events":{"description":"Array of event series that were synced. Each series contains its event instances","type":"array","items":{"type":"object","properties":{"event_type":{"description":"The type of event. 'one_off' for single events, 'recurring' for events that are part of a recurring series","type":"string","enum":["one_off","recurring"]},"series_id":{"description":"The UUID of the event series. Null only in rare cases where the series relationship could not be established","anyOf":[{"type":"string","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":"null"}]},"series_bot_scheduled":{"description":"Whether a bot has been scheduled for all occurrences of this series. True if a calendar bot schedule exists for the entire series","type":"boolean"},"instances":{"description":"Array of event instances that were synced. For one-off events, this contains a single instance. For recurring events, this contains all instances that were synced","type":"array","items":{"type":"object","properties":{"event_id":{"description":"The UUID of the event instance","type":"string","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)$"},"start":{"description":"ISO 8601 timestamp when the event starts","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"end":{"description":"ISO 8601 timestamp when the event ends","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"title":{"description":"The title of the event","type":"string"},"status":{"description":"The status of the event. Possible values: 'confirmed' (event is confirmed), 'cancelled' (event has been cancelled), 'tentative' (event is tentative)","type":"string","enum":["confirmed","cancelled","tentative"]},"is_all_day":{"description":"Whether this is an all-day event. True if the event spans entire days without specific start/end times","type":"boolean"},"is_exception":{"description":"Whether this is an exception to a recurring series. True if this instance has been modified differently from the recurring pattern","type":"boolean"},"bot_scheduled":{"description":"Whether a bot has been scheduled for this event instance. True if a calendar bot schedule exists for this event","type":"boolean"},"meeting_url":{"description":"The meeting URL extracted from the event. Null if the calendar platform did not include a meeting link in the event","anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"meeting_platform":{"description":"The meeting platform detected from the meeting URL. Null if no meeting link was found in the event. Possible values: 'zoom', 'meet', or 'teams'","anyOf":[{"type":"string","enum":["zoom","meet","teams"]},{"type":"null"}]}},"required":["event_id","start","end","title","status","is_all_day","is_exception","bot_scheduled","meeting_url","meeting_platform"]}}},"required":["event_type","series_id","series_bot_scheduled","instances"]}}},"required":["calendar_id","events"]}},"required":["event","data"]},"CalendarWebhookEventCreatedInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/CalendarWebhookEventCreatedInput","type":"object","properties":{"event":{"description":"The webhook event type","type":"string","const":"calendar.event_created"},"data":{"type":"object","properties":{"calendar_id":{"description":"The UUID of the calendar connection where the event was created","type":"string","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)$"},"event_type":{"description":"The type of event. 'one_off' for single events, 'recurring' for events that are part of a recurring series","type":"string","enum":["one_off","recurring"]},"series_id":{"description":"The UUID of the event series. Null only in rare cases where the series relationship could not be established","anyOf":[{"type":"string","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":"null"}]},"series_bot_scheduled":{"description":"Whether a bot has been scheduled for all occurrences of this series. True if a calendar bot schedule exists for the entire series","type":"boolean"},"instances":{"description":"Array of event instances that were created. For one-off events, this contains a single instance. For recurring events, this contains all instances that were created","type":"array","items":{"type":"object","properties":{"event_id":{"description":"The UUID of the event instance","type":"string","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)$"},"start":{"description":"ISO 8601 timestamp when the event starts","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"end":{"description":"ISO 8601 timestamp when the event ends","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"title":{"description":"The title of the event","type":"string"},"status":{"description":"The status of the event. Possible values: 'confirmed' (event is confirmed), 'cancelled' (event has been cancelled), 'tentative' (event is tentative)","type":"string","enum":["confirmed","cancelled","tentative"]},"is_all_day":{"description":"Whether this is an all-day event. True if the event spans entire days without specific start/end times","type":"boolean"},"is_exception":{"description":"Whether this is an exception to a recurring series. True if this instance has been modified differently from the recurring pattern","type":"boolean"},"bot_scheduled":{"description":"Whether a bot has been scheduled for this event instance. True if a calendar bot schedule exists for this event","type":"boolean"},"meeting_url":{"description":"The meeting URL extracted from the event. Null if the calendar platform did not include a meeting link in the event","anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"meeting_platform":{"description":"The meeting platform detected from the meeting URL. Null if no meeting link was found in the event. Possible values: 'zoom', 'meet', or 'teams'","anyOf":[{"type":"string","enum":["zoom","meet","teams"]},{"type":"null"}]}},"required":["event_id","start","end","title","status","is_all_day","is_exception","bot_scheduled","meeting_url","meeting_platform"]}}},"required":["calendar_id","event_type","series_id","series_bot_scheduled","instances"]}},"required":["event","data"]},"CalendarWebhookEventUpdatedInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/CalendarWebhookEventUpdatedInput","type":"object","properties":{"event":{"description":"The webhook event type","type":"string","const":"calendar.event_updated"},"data":{"type":"object","properties":{"calendar_id":{"description":"The UUID of the calendar connection where the event was updated","type":"string","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)$"},"event_type":{"description":"The type of event. 'one_off' for single events, 'recurring' for events that are part of a recurring series","type":"string","enum":["one_off","recurring"]},"series_id":{"description":"The UUID of the event series. Null only in rare cases where the series relationship could not be established","anyOf":[{"type":"string","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":"null"}]},"series_bot_scheduled":{"description":"Whether a bot has been scheduled for all occurrences of this series. True if a calendar bot schedule exists for the entire series","type":"boolean"},"is_exception":{"description":"Whether the updated instance is an exception to a recurring series. True if this instance has been modified differently from the recurring pattern","type":"boolean"},"affected_instances":{"description":"Array of event instances that were affected by the update. This includes the instance that was directly updated and any related instances","type":"array","items":{"type":"object","properties":{"event_id":{"description":"The UUID of the event instance","type":"string","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)$"},"start":{"description":"ISO 8601 timestamp when the event starts","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"end":{"description":"ISO 8601 timestamp when the event ends","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"title":{"description":"The title of the event","type":"string"},"status":{"description":"The status of the event. Possible values: 'confirmed' (event is confirmed), 'cancelled' (event has been cancelled), 'tentative' (event is tentative)","type":"string","enum":["confirmed","cancelled","tentative"]},"is_all_day":{"description":"Whether this is an all-day event. True if the event spans entire days without specific start/end times","type":"boolean"},"is_exception":{"description":"Whether this is an exception to a recurring series. True if this instance has been modified differently from the recurring pattern","type":"boolean"},"bot_scheduled":{"description":"Whether a bot has been scheduled for this event instance. True if a calendar bot schedule exists for this event","type":"boolean"},"meeting_url":{"description":"The meeting URL extracted from the event. Null if the calendar platform did not include a meeting link in the event","anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"meeting_platform":{"description":"The meeting platform detected from the meeting URL. Null if no meeting link was found in the event. Possible values: 'zoom', 'meet', or 'teams'","anyOf":[{"type":"string","enum":["zoom","meet","teams"]},{"type":"null"}]}},"required":["event_id","start","end","title","status","is_all_day","is_exception","bot_scheduled","meeting_url","meeting_platform"]}}},"required":["calendar_id","event_type","series_id","series_bot_scheduled","is_exception","affected_instances"]}},"required":["event","data"]},"CalendarWebhookEventCancelledInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/CalendarWebhookEventCancelledInput","type":"object","properties":{"event":{"description":"The webhook event type","type":"string","const":"calendar.event_cancelled"},"data":{"type":"object","properties":{"calendar_id":{"description":"The UUID of the calendar connection where the event was cancelled","type":"string","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)$"},"event_type":{"description":"The type of event. 'one_off' for single events, 'recurring' for events that are part of a recurring series","type":"string","enum":["one_off","recurring"]},"series_id":{"description":"The UUID of the event series. Null only in rare cases where the series relationship could not be established","anyOf":[{"type":"string","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":"null"}]},"cancelled_instances":{"description":"Array of event instances that were cancelled. For one-off events, this contains a single instance. For recurring events, this contains all instances that were cancelled","type":"array","items":{"type":"object","properties":{"event_id":{"description":"The UUID of the event instance","type":"string","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)$"},"start":{"description":"ISO 8601 timestamp when the event starts","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"end":{"description":"ISO 8601 timestamp when the event ends","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"title":{"description":"The title of the event","type":"string"},"status":{"description":"The status of the event. Possible values: 'confirmed' (event is confirmed), 'cancelled' (event has been cancelled), 'tentative' (event is tentative)","type":"string","enum":["confirmed","cancelled","tentative"]},"is_all_day":{"description":"Whether this is an all-day event. True if the event spans entire days without specific start/end times","type":"boolean"},"is_exception":{"description":"Whether this is an exception to a recurring series. True if this instance has been modified differently from the recurring pattern","type":"boolean"},"bot_scheduled":{"description":"Whether a bot has been scheduled for this event instance. True if a calendar bot schedule exists for this event","type":"boolean"},"meeting_url":{"description":"The meeting URL extracted from the event. Null if the calendar platform did not include a meeting link in the event","anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"meeting_platform":{"description":"The meeting platform detected from the meeting URL. Null if no meeting link was found in the event. Possible values: 'zoom', 'meet', or 'teams'","anyOf":[{"type":"string","enum":["zoom","meet","teams"]},{"type":"null"}]}},"required":["event_id","start","end","title","status","is_all_day","is_exception","bot_scheduled","meeting_url","meeting_platform"]}}},"required":["calendar_id","event_type","series_id","cancelled_instances"]}},"required":["event","data"]},"CallbackCompletedInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/CallbackCompletedInput","type":"object","properties":{"event":{"description":"The webhook event type","type":"string","const":"bot.completed"},"data":{"type":"object","properties":{"bot_id":{"description":"The UUID of the bot that completed","type":"string","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)$"},"event_id":{"description":"The UUID of the calendar event associated with this bot. Null for non-calendar bots","anyOf":[{"type":"string","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":"null"}]},"participants":{"description":"List of participants who joined the meeting with their names and metadata. Empty array if participant information is not available","type":"array","items":{"type":"object","properties":{"name":{"description":"Participant's name (full name or display name)","type":"string"},"id":{"description":"Sequential participant ID (1, 2, 3...). Null if not available","anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"display_name":{"description":"Display name shown in UI (if different from name)","type":"string"},"profile_picture":{"description":"Profile picture URL (if available)","type":"string","format":"uri"}},"required":["name","id"]}},"speakers":{"description":"List of speakers detected in the meeting with their names and metadata. Empty array if speaker information is not available","type":"array","items":{"type":"object","properties":{"name":{"description":"Participant's name (full name or display name)","type":"string"},"id":{"description":"Sequential participant ID (1, 2, 3...). Null if not available","anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"display_name":{"description":"Display name shown in UI (if different from name)","type":"string"},"profile_picture":{"description":"Profile picture URL (if available)","type":"string","format":"uri"}},"required":["name","id"]}},"duration_seconds":{"anyOf":[{"description":"The duration of the meeting in seconds. Null if duration could not be determined","type":"integer","minimum":0,"maximum":9007199254740991},{"type":"null"}]},"joined_at":{"description":"ISO 8601 timestamp when the bot joined the meeting. Null if join time is not available","anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"exited_at":{"description":"ISO 8601 timestamp when the bot exited the meeting. Null if exit time is not available","anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"data_deleted":{"description":"Whether the bot's data (artifacts, recordings) has been deleted. True if data has been permanently removed","type":"boolean"},"video":{"description":"Signed URL to download the video recording. Valid for 4 hours. Null if video recording is not available or has been deleted","anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"audio":{"description":"Signed URL to download the audio recording. Valid for 4 hours. Null if audio recording is not available or has been deleted","anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"diarization":{"description":"Signed URL to download the speaker diarization data. Valid for 4 hours. Null if diarization is not available or has been deleted","anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"raw_transcription":{"description":"Signed URL to download the raw transcription file. Valid for 4 hours. Null if raw transcription is not available or has been deleted","anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"transcription":{"description":"Signed URL to download the processed transcription file. Valid for 4 hours. Null if transcription is not available or has been deleted","anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"transcription_provider":{"description":"The transcription provider used (e.g., 'gladia'). Null if transcription was not enabled or if provider information is not available","anyOf":[{"type":"string"},{"type":"null"}]},"transcription_ids":{"description":"Array of transcription job IDs from the transcription provider. Null if transcription was not enabled or if IDs are not available","anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}]},"sent_at":{"description":"ISO 8601 timestamp when this webhook was sent","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["bot_id","event_id","participants","speakers","duration_seconds","joined_at","exited_at","data_deleted","video","audio","diarization","raw_transcription","transcription","transcription_provider","transcription_ids","sent_at"]},"extra":{"description":"Additional metadata provided when creating the bot. This is user-defined data that can be used for correlation or tracking","anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]}},"required":["event","data","extra"]},"CallbackFailedInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/CallbackFailedInput","type":"object","properties":{"event":{"description":"The webhook event type","type":"string","const":"bot.failed"},"data":{"type":"object","properties":{"bot_id":{"description":"The UUID of the bot that failed","type":"string","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)$"},"event_id":{"description":"The UUID of the calendar event associated with this bot. Null for non-calendar bots","anyOf":[{"type":"string","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":"null"}]},"error_message":{"description":"Human-readable error message describing why the bot failed","type":"string"},"error_code":{"description":"Machine-readable error code for programmatic handling. Common codes include 'MEETING_NOT_FOUND', 'MEETING_ENDED', 'BOT_CRASHED', etc.","type":"string"},"sent_at":{"description":"ISO 8601 timestamp when this webhook was sent","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["bot_id","event_id","error_message","error_code","sent_at"]},"extra":{"description":"Additional metadata provided when creating the bot. This is user-defined data that can be used for correlation or tracking","anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]}},"required":["event","data","extra"]},"OutputTranscriptionInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/OutputTranscriptionInput","type":"object","properties":{"bot_id":{"description":"The bot UUID","type":"string","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)$"},"provider":{"description":"The transcription provider","type":"string","const":"gladia"},"result":{"type":"object","properties":{"utterances":{"description":"Array of diarized utterances, sorted chronologically","type":"array","items":{"type":"object","properties":{"text":{"description":"The transcribed text for this utterance","type":"string"},"language":{"description":"ISO 639-1 language code (e.g., 'en', 'es')","type":"string"},"start":{"description":"Start time in seconds (floating point)","type":"number"},"end":{"description":"End time in seconds (floating point)","type":"number"},"confidence":{"description":"Confidence score (0.0 to 1.0)","type":"number","minimum":0,"maximum":1},"channel":{"description":"Audio channel number","type":"number"},"words":{"description":"Array of word-level timestamps","type":"array","items":{"type":"object","properties":{"word":{"description":"The word text","type":"string"},"start":{"description":"Start time in seconds","type":"number"},"end":{"description":"End time in seconds","type":"number"},"confidence":{"description":"Confidence score (0.0 to 1.0)","type":"number","minimum":0,"maximum":1}},"required":["word","start","end","confidence"]}},"speaker":{"description":"Real speaker name","type":"string"}},"required":["text","language","start","end","confidence","channel","words","speaker"]}},"languages":{"description":"Array of detected language codes","type":"array","items":{"type":"string"}},"total_utterances":{"description":"Total number of utterances","type":"integer","minimum":0,"maximum":9007199254740991},"total_duration":{"description":"Total duration of the meeting in seconds","type":"number","minimum":0}},"required":["utterances","languages","total_utterances","total_duration"]},"created_at":{"description":"ISO 8601 timestamp when the transcription was created","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["bot_id","provider","result","created_at"]},"ZoomDiarizationSegmentInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/ZoomDiarizationSegmentInput","type":"object","properties":{"speaker":{"description":"Real speaker name","type":"string"},"start_time":{"description":"Start time in seconds","type":"number"},"end_time":{"description":"End time in seconds","type":"number"},"user_id":{"description":"Platform user ID (Zoom only)","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"lang":{"description":"Language code (optional)","type":"string"}},"required":["speaker","start_time","end_time","user_id"]},"MeetTeamsDiarizationSegmentInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/MeetTeamsDiarizationSegmentInput","type":"object","properties":{"speaker":{"description":"Real speaker name","type":"string"},"start_time":{"description":"Start time in seconds","type":"number"},"end_time":{"description":"End time in seconds","type":"number"}},"required":["speaker","start_time","end_time"]},"DiarizationSegmentInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/DiarizationSegmentInput","anyOf":[{"$ref":"#/components/schemas/ZoomDiarizationSegmentInput"},{"$ref":"#/components/schemas/MeetTeamsDiarizationSegmentInput"}]},"RawTranscriptionInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/RawTranscriptionInput","type":"object","properties":{"bot_id":{"description":"The bot UUID","type":"string","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)$"},"transcriptions":{"description":"Array of transcription payloads, one per audio chunk","type":"array","items":{"description":"Gladia transcription payload with provider-specific features. Additional fields may be present based on custom parameters.","type":"object","properties":{"metadata":{"type":"object","properties":{"audio_duration":{"description":"Audio duration in seconds","type":"number"},"number_of_distinct_channels":{"description":"Number of distinct audio channels","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"billing_time":{"description":"Billing time in seconds","type":"number"},"transcription_time":{"description":"Transcription processing time in seconds","type":"number"}},"required":["audio_duration","number_of_distinct_channels","billing_time","transcription_time"]},"transcription":{"type":"object","properties":{"full_transcript":{"description":"Full transcript text","type":"string"},"languages":{"description":"Array of detected language codes","type":"array","items":{"type":"string"}},"utterances":{"description":"Array of utterances","type":"array","items":{"type":"object","properties":{"text":{"type":"string"},"language":{"type":"string"},"start":{"type":"number"},"end":{"type":"number"},"confidence":{"type":"number","minimum":0,"maximum":1},"channel":{"type":"number"},"words":{"type":"array","items":{"type":"object","properties":{"word":{"type":"string"},"start":{"type":"number"},"end":{"type":"number"},"confidence":{"type":"number","minimum":0,"maximum":1}},"required":["word","start","end","confidence"]}},"speaker":{"description":"Gladia's numeric speaker ID (0, 1, 2, etc.)","type":"number"}},"required":["text","language","start","end","confidence","channel","words","speaker"]}},"error":{"description":"Error information if transcription failed"}},"required":["languages","utterances"]},"summarization":{"description":"AI-generated meeting summary","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"translation":{"description":"Translated transcriptions by target language","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"sentiment_analysis":{"description":"Sentiment scores for utterances","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"named_entity_recognition":{"description":"Extracted entities (names, organizations, locations)","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"audio_to_llm":{"description":"LLM prompt responses","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"moderation":{"description":"Content moderation results","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"chapterization":{"description":"Automatic meeting chapters","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["metadata","transcription"],"additionalProperties":{}}},"created_at":{"description":"ISO 8601 timestamp when the combined transcription was created","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["bot_id","transcriptions","created_at"]},"ErrorResponse":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/ErrorResponse","type":"object","properties":{"success":{"default":false,"type":"boolean","const":false},"error":{"description":"Human-readable error message","type":"string"},"code":{"description":"Error code for programmatic handling","type":"string"},"statusCode":{"description":"HTTP status code","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"message":{"description":"Human-readable error message","anyOf":[{"type":"string"},{"type":"null"}]},"details":{"description":"Additional error details (string or null)","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["success","error","code","statusCode"],"additionalProperties":false},"ValidationErrorResponse":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/ValidationErrorResponse","type":"object","properties":{"success":{"default":false,"type":"boolean","const":false},"error":{"description":"Error name","type":"string"},"code":{"description":"Error code for programmatic handling","type":"string"},"statusCode":{"description":"HTTP status code","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"message":{"description":"Human-readable error message","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["success","error","code","statusCode"],"additionalProperties":false},"CreateBotRequestBody":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/CreateBotRequestBody"},"BatchCreateBotsRequestBody":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/BatchCreateBotsRequestBody","minItems":1,"maxItems":100,"type":"array","items":{"$ref":"#/components/schemas/CreateBotRequestBody"}},"RetryCallbackRequestBody":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/RetryCallbackRequestBody","description":"Optional callback configuration to override the bot's configured callback.\n\nIf provided, all fields must be included and these values will be used instead of the bot's original callback configuration. If omitted (null), the bot's original callback configuration will be used.\n\n- `url`: Custom callback URL (overrides configured URL)\n- `method`: HTTP method (`POST` or `PUT`, default: `POST`)\n- `secret`: Custom HMAC secret (overrides configured secret, sent in `x-mb-secret` header)","default":null,"anyOf":[{"example":null,"type":"object","properties":{"url":{"description":"The URL to be called upon the completion or failure of the bot.","type":"string","format":"uri"},"secret":{"description":"To ensure that you can validate the callback, this secret will be added to the request in the 'x-mb-secret' header","example":null,"default":null,"anyOf":[{"type":"string"},{"type":"null"}]},"method":{"description":"The HTTP method to use for the callback. Allowed values are 'POST' or 'PUT'.","default":"POST","type":"string","enum":["POST","PUT"]}},"required":["url","secret","method"],"additionalProperties":false},{"type":"null"}]},"CreateBotResponse":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/CreateBotResponse","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"object","properties":{"bot_id":{"description":"The UUID of the created bot","type":"string","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)$"}},"required":["bot_id"],"additionalProperties":false}},"required":["success","data"],"additionalProperties":false},"BatchCreateBotResponse":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/BatchCreateBotResponse","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"description":"Successfully created bots","type":"array","items":{"type":"object","properties":{"index":{"description":"0-based index of the item in the request array","type":"integer","minimum":0,"maximum":9007199254740991},"bot_id":{"description":"The UUID of the created bot","type":"string","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)$"},"extra":{"description":"Custom metadata from the request (for correlation)","anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]}},"required":["index","bot_id","extra"],"additionalProperties":false}},"errors":{"description":"Bots that failed to create (empty array if all succeeded)","type":"array","items":{"type":"object","properties":{"index":{"description":"0-based index of the item in the request array","type":"integer","minimum":0,"maximum":9007199254740991},"code":{"description":"Error code for programmatic handling","type":"string"},"message":{"description":"Human-readable error message","type":"string"},"details":{"description":"Additional error details (null if no additional details)","anyOf":[{"type":"string"},{"type":"null"}]},"extra":{"description":"Custom metadata from the request (for correlation)","anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]}},"required":["index","code","message","details","extra"],"additionalProperties":false}}},"required":["success","data","errors"],"additionalProperties":false},"ListBotsResponse":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/ListBotsResponse","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"array","items":{"type":"object","properties":{"bot_id":{"description":"The UUID of the bot","type":"string","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)$"},"bot_name":{"description":"The name of the bot","type":"string"},"meeting_url":{"description":"The URL of the meeting","type":"string","format":"uri"},"meeting_platform":{"description":"The platform of the meeting (zoom, meet, or teams)","type":"string","enum":["zoom","meet","teams"]},"extra":{"description":"Custom metadata associated with the bot","anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]},"duration":{"description":"Duration of the meeting in seconds (null if meeting hasn't ended)","anyOf":[{"type":"number"},{"type":"null"}]},"created_at":{"description":"ISO 8601 timestamp when the bot was created","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"ended_at":{"description":"ISO 8601 timestamp when the bot ended (null if still active)","anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"joined_at":{"description":"ISO 8601 timestamp when the bot joined the meeting (null if not joined yet)","anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"exited_at":{"description":"ISO 8601 timestamp when the bot exited the meeting (null if not exited yet)","anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"status":{"description":"The current status of the bot","type":"string","enum":["queued","transcribing","completed","failed","joining_call","in_waiting_room","in_waiting_for_host","in_call_not_recording","in_call_recording","recording_paused","recording_resumed","call_ended","recording_succeeded","recording_failed","api_request_stop","bot_rejected","bot_removed","bot_removed_too_early","waiting_room_timeout","invalid_meeting_url","meeting_error"]},"error_code":{"description":"Error code if the bot failed (null if no error)","anyOf":[{"type":"string"},{"type":"null"}]},"error_message":{"description":"Human-readable error message if the bot failed (null if no error)","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["bot_id","bot_name","meeting_url","meeting_platform","extra","duration","created_at","ended_at","joined_at","exited_at","status","error_code","error_message"],"additionalProperties":false}},"cursor":{"description":"Cursor for the next page (null if no more pages)","anyOf":[{"type":"string"},{"type":"null"}]},"prev_cursor":{"description":"Cursor for the previous page (null if on first page)","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["success","data","cursor","prev_cursor"],"additionalProperties":false},"GetBotDetailsResponse":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/GetBotDetailsResponse","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"object","properties":{"bot_id":{"description":"The UUID of the bot","type":"string","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)$"},"bot_name":{"description":"The name of the bot","type":"string"},"meeting_url":{"description":"The URL of the meeting","type":"string","format":"uri"},"meeting_platform":{"description":"The platform of the meeting","type":"string","enum":["zoom","meet","teams"]},"recording_mode":{"description":"The recording mode used by the bot","type":"string","enum":["audio_only","speaker_view","gallery_view"]},"status":{"description":"The current status of the bot","type":"string","enum":["queued","transcribing","completed","failed","joining_call","in_waiting_room","in_waiting_for_host","in_call_not_recording","in_call_recording","recording_paused","recording_resumed","call_ended","recording_succeeded","recording_failed","api_request_stop","bot_rejected","bot_removed","bot_removed_too_early","waiting_room_timeout","invalid_meeting_url","meeting_error"]},"created_at":{"description":"ISO 8601 timestamp when the bot was created","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"joined_at":{"description":"ISO 8601 timestamp when the bot joined the meeting (null if not joined yet)","anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"exited_at":{"description":"ISO 8601 timestamp when the bot exited the meeting (null if not exited yet)","anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"duration_seconds":{"description":"Duration of the meeting in seconds (null if meeting hasn't ended)","anyOf":[{"type":"number"},{"type":"null"}]},"participants":{"description":"List of participants who joined the meeting with their names and metadata","type":"array","items":{"type":"object","properties":{"name":{"description":"Participant's name (full name or display name)","type":"string"},"id":{"description":"Sequential participant ID (1, 2, 3...). Null if not available","anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"display_name":{"description":"Display name shown in UI (if different from name)","type":"string"},"profile_picture":{"description":"Profile picture URL (if available)","type":"string","format":"uri"}},"required":["name","id"],"additionalProperties":false}},"speakers":{"description":"List of speakers identified in the meeting with their names and metadata","type":"array","items":{"type":"object","properties":{"name":{"description":"Participant's name (full name or display name)","type":"string"},"id":{"description":"Sequential participant ID (1, 2, 3...). Null if not available","anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"display_name":{"description":"Display name shown in UI (if different from name)","type":"string"},"profile_picture":{"description":"Profile picture URL (if available)","type":"string","format":"uri"}},"required":["name","id"],"additionalProperties":false}},"artifacts_deleted":{"description":"Whether the artifacts have been deleted","type":"boolean"},"video":{"description":"Signed URL to the video recording (valid for 4 hours, null if not available)","anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"audio":{"description":"Signed URL to the audio recording (valid for 4 hours, null if not available)","anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"diarization":{"description":"Signed URL to the diarization file (valid for 4 hours, null if not available)","anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"raw_transcription":{"description":"Signed URL to the raw transcription file (valid for 4 hours, null if not available)","anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"transcription":{"description":"Signed URL to the transcription file (valid for 4 hours, null if not available)","anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"chat_messages":{"description":"Signed URL to the chat messages JSON file (valid for 4 hours, null if not available)","anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"transcription_ids":{"description":"Array of transcription job IDs from the transcription provider","anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}]},"transcription_provider":{"description":"The transcription provider used (null if transcription is disabled or provider is 'none')","anyOf":[{"type":"string","enum":["gladia"]},{"type":"null"}]},"error_code":{"description":"Error code if the bot failed (null if no error)","anyOf":[{"type":"string"},{"type":"null"}]},"error_message":{"description":"Human-readable error message if the bot failed (null if no error)","anyOf":[{"type":"string"},{"type":"null"}]},"extra":{"description":"Custom metadata associated with the bot","anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]},"zoom_config":{"description":"Zoom configuration for this bot (null if not a Zoom bot or no zoom config provided)","anyOf":[{"type":"object","properties":{"credential_id":{"description":"UUID of the stored Zoom credential","anyOf":[{"type":"string","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":"null"}]},"credential_user_id":{"description":"Zoom user ID used to look up the credential","anyOf":[{"type":"string"},{"type":"null"}]},"obf_token_url":{"description":"URL that returns an OBF token at join time","anyOf":[{"type":"string"},{"type":"null"}]},"zak_token_url":{"description":"URL that returns a ZAK token at join time","anyOf":[{"type":"string"},{"type":"null"}]}},"additionalProperties":false},{"type":"null"}]}},"required":["bot_id","bot_name","meeting_url","meeting_platform","recording_mode","status","created_at","joined_at","exited_at","duration_seconds","participants","speakers","artifacts_deleted","video","audio","diarization","raw_transcription","transcription","chat_messages","transcription_ids","transcription_provider","error_code","error_message","extra","zoom_config"],"additionalProperties":false}},"required":["success","data"],"additionalProperties":false},"GetBotStatusResponse":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/GetBotStatusResponse","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"object","properties":{"bot_id":{"description":"The UUID of the bot","type":"string","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)$"},"status":{"description":"The current status of the bot","type":"string","enum":["queued","transcribing","completed","failed","joining_call","in_waiting_room","in_waiting_for_host","in_call_not_recording","in_call_recording","recording_paused","recording_resumed","call_ended","recording_succeeded","recording_failed","api_request_stop","bot_rejected","bot_removed","bot_removed_too_early","waiting_room_timeout","invalid_meeting_url","meeting_error"]},"transcription_status":{"description":"The current transcription status","type":"string","enum":["queued","processing","done","error","not-applicable","not-started"]},"updated_at":{"description":"ISO 8601 timestamp when the status was last updated","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["bot_id","status","transcription_status","updated_at"],"additionalProperties":false}},"required":["success","data"],"additionalProperties":false},"GetBotScreenshotsResponse":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/GetBotScreenshotsResponse","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"array","items":{"type":"object","properties":{"screenshot_id":{"description":"The index of the screenshot (1-based)","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"url":{"description":"Signed URL to the screenshot (valid for 4 hours)","type":"string","format":"uri"}},"required":["screenshot_id","url"],"additionalProperties":false}},"cursor":{"description":"Cursor for the next page (null if no more pages)","anyOf":[{"type":"string"},{"type":"null"}]},"prev_cursor":{"description":"Cursor for the previous page (null if on first page)","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["success","data","cursor","prev_cursor"],"additionalProperties":false},"LeaveBotResponse":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/LeaveBotResponse","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"object","properties":{"message":{"description":"Success message","type":"string"}},"required":["message"],"additionalProperties":false}},"required":["success","data"],"additionalProperties":false},"DeleteBotDataResponse":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/DeleteBotDataResponse","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"object","properties":{"message":{"description":"Success message","type":"string"}},"required":["message"],"additionalProperties":false}},"required":["success","data"],"additionalProperties":false},"ResendFinalWebhookResponse":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/ResendFinalWebhookResponse","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"object","properties":{"message":{"description":"Success message","type":"string"}},"required":["message"],"additionalProperties":false}},"required":["success","data"],"additionalProperties":false},"RetryCallbackResponse":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/RetryCallbackResponse","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"object","properties":{"message":{"description":"Success message","type":"string"}},"required":["message"],"additionalProperties":false}},"required":["success","data"],"additionalProperties":false},"CreateScheduledBotRequestBody":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/CreateScheduledBotRequestBody","allOf":[{"$ref":"#/components/schemas/CreateBotRequestBody"},{"type":"object","properties":{"join_at":{"description":"ISO8601 timestamp when the bot should join the meeting.\n\nCannot be in the past (with 1 minute leeway) and cannot be more than 90 days in the future.\n\nExample: \"2025-12-25T10:00:00Z\"","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["join_at"],"additionalProperties":false}]},"BatchCreateScheduledBotsRequestBody":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/BatchCreateScheduledBotsRequestBody","minItems":1,"maxItems":100,"type":"array","items":{"$ref":"#/components/schemas/CreateScheduledBotRequestBody"}},"UpdateScheduledBotRequestBody":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/UpdateScheduledBotRequestBody","type":"object","properties":{"bot_name":{"description":"The name of the bot.\n\nThis name will be displayed as the bot's name in the meeting.","example":"Meeting BaaS Bot","type":"string","minLength":1,"maxLength":255},"bot_image":{"description":"The bot's avatar image(s).\n\nAccepts a single HTTPS URL or an array of up to 5 HTTPS URLs pointing to image files (JPEG, PNG, or WebP). When multiple images are provided, they will be cycled based on the bot_image_config settings.","example":null,"default":null,"anyOf":[{"anyOf":[{"type":"string","format":"uri"},{"minItems":1,"maxItems":5,"type":"array","items":{"type":"string","format":"uri"}}]},{"type":"null"}]},"bot_image_config":{"description":"Configuration for how bot avatar images are displayed. Only relevant when multiple images are provided in bot_image.","example":null,"default":null,"anyOf":[{"type":"object","properties":{"loop_mode":{"description":"Controls how multiple bot images are cycled.\n\n- `auto`: Cycles through images at the interval specified by image_duration.\n- `bot_status`: Uses the first image when the bot joins, and the second image when recording starts. Only the first two images are used in this mode; additional images are ignored.","default":"auto","type":"string","enum":["auto","bot_status"]},"image_duration":{"description":"Duration in seconds each image is displayed before switching to the next. Only used when loop_mode is 'auto'.\n\nDefault: 30. Range: 10-120.","default":30,"type":"integer","minimum":10,"maximum":120}},"required":["loop_mode","image_duration"],"additionalProperties":false},{"type":"null"}]},"meeting_url":{"description":"The URL of the meeting to join.\n\nMust be a valid HTTPS URL for a Microsoft Teams, Google Meet, or Zoom meeting.\n\nExample: \"https://zoom.us/j/123456789\" or \"https://meet.google.com/abc-defg-hij\"","example":"","type":"string","format":"uri"},"allow_multiple_bots":{"description":"Whether to allow multiple bots to join the same meeting.\n\nIf set to `false`, only a single bot will be allowed to join using the same meeting URL within the last 5 minutes. This prevents duplicate bots from joining the same meeting.\n\nIf set to `true` (default), multiple bots can join the same meeting URL.\n\nDefault: `true`","example":true,"default":true,"type":"boolean"},"recording_mode":{"description":"The recording mode of the bot.\n\nDetermines what the bot records during the meeting:\n\n- `speaker_view`: Records the speaker's view (default). Shows the active speaker or presenter.\n- `audio_only`: Records only the audio without video.\n- `gallery_view`: Records the entire gallery view (coming soon).\n\nDefault: `speaker_view`","example":"speaker_view","default":"speaker_view","type":"string","enum":["audio_only","speaker_view","gallery_view"]},"entry_message":{"description":"The message that the bot will send when it joins the meeting.\n\nThis message will be posted in the meeting chat when the bot successfully joins.\n\nAvailable for Google Meet, Microsoft Teams, and Zoom meetings.\n\nMaximum: 500 characters","example":"Hello! I'm here to record this meeting.","default":null,"anyOf":[{"type":"string","maxLength":500},{"type":"null"}]},"timeout_config":{"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.","default":{"waiting_room_timeout":600,"no_one_joined_timeout":600,"silence_timeout":600},"type":"object","properties":{"waiting_room_timeout":{"description":"The timeout in seconds for the bot to wait in the waiting room before leaving the meeting.\n\nIf the bot is placed in a waiting room and not admitted within this time, it will leave the meeting.\n\nNote: Google Meet has its own waiting room timeout (approximately 10 minutes). Setting a higher value for Google Meet meetings will have no effect, as Google Meet will deny entry to the bot after its own timeout.\n\nDefault: 600 seconds (10 minutes)\nMinimum: 2 minutes\nMaximum: 30 minutes","example":600,"default":600,"type":"integer","minimum":120,"maximum":1800},"no_one_joined_timeout":{"description":"The timeout in seconds for the bot to wait for participants to join before leaving the meeting.\n\nIf no participants join the meeting within this time after the bot joins, the bot will leave the meeting. Only applicable for Google Meet and Microsoft Teams meetings.\n\nDefault: 600 seconds (10 minutes)\nMinimum: 2 minutes\nMaximum: 30 minutes","example":600,"default":600,"type":"integer","minimum":120,"maximum":1800},"silence_timeout":{"description":"The timeout in seconds for the bot to wait for silence before leaving the meeting.\n\nIf no audio is detected for this duration after the bot joins, the bot will leave the meeting. Only applicable for Google Meet and Microsoft Teams meetings.\n\nDefault: 600 seconds (10 minutes)\nMinimum: 5 minutes\nMaximum: 30 minutes","example":600,"default":600,"type":"integer","minimum":300,"maximum":1800}},"required":["waiting_room_timeout","no_one_joined_timeout","silence_timeout"],"additionalProperties":false},"zoom_config":{"description":"Zoom-only configuration for authentication and join method.\n\n- **credential_id**: Use a stored Zoom credential (OBF token fetched by the bot from the API server).\n- **credential_user_id**: Resolve a stored credential by Zoom user ID.\n- **obf_token**: Provide a direct OBF token (one-off join).\n- **obf_token_url**: URL that returns an OBF token when the bot joins.\n- **zak_token_url**: URL that returns a ZAK for joining without the host.\n\nLeave `null` for Google Meet and Microsoft Teams.","example":null,"default":null,"anyOf":[{"type":"object","properties":{"credential_id":{"description":"UUID of a stored Zoom credential (created via Zoom credentials API). The bot will fetch the OBF token from the API server using this ID. Use this when you have saved a Zoom OAuth credential and want the bot to join on behalf of that user.","type":"string","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)$"},"credential_user_id":{"description":"Zoom user ID (e.g. from the Zoom profile) to look up a stored credential by user. The API server will resolve this to a credential_id. Use when you have multiple credentials and want to target a specific user.","type":"string"},"obf_token":{"description":"Direct OBF (On-Behalf-Of) token. Use this to join a Zoom meeting as a specific user without storing a credential. The token is a JWT issued by Zoom; the bot uses it once to join. Suitable for short-lived or one-off joins. For recurring use, prefer credential_id or obf_token_url.","type":"string"},"obf_token_url":{"description":"URL that returns an OBF token at join time. The bot will make a GET request with query params: bot_uuid (bot UUID) and extra (URL-encoded JSON of the run's extra payload). Use these to identify which bot/run is requesting the token. Response must be plain text (ASCII) containing the OBF token. Timeout: 15 seconds.","type":"string","format":"uri"},"zak_token_url":{"description":"URL to get the Zoom ZAK (Zoom Access Token). The bot makes a GET request with query params: bot_uuid and extra (URL-encoded JSON). Use these to identify which bot/run is requesting the token. Response must be plain text (ASCII) with the raw ZAK. See https://developers.zoom.us/docs/api/users/#tag/users/get/users/me/zak. Timeout: 15 seconds.","type":"string","format":"uri"}},"additionalProperties":false},{"type":"null"}]},"extra":{"description":"An optional extra configuration object for the bot.\n\nThis object can contain any custom key-value pairs that you want to associate with the bot. The data will be:\n\n- Included in all webhook event payloads (if a webhook endpoint is configured)\n- Part of the callback payload (if callback is enabled)\n- Returned when fetching the bot's details via the API\n\nUseful for storing custom metadata, tracking information, or any other data you need to correlate with the bot.","example":null,"default":null,"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]},"streaming_enabled":{"description":"Enable audio streaming for this bot. When enabled, the streaming_config property is used to provide the configuration.","default":false,"type":"boolean"},"streaming_config":{"default":null,"anyOf":[{"example":null,"type":"object","properties":{"input_url":{"description":"Websocket stream URL, which receives the audio sent to the bot, and the bot will stream the audio to the meeting.","example":null,"default":null,"anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"output_url":{"description":"Websocket stream URL, which the bot sends the audio to. This is used to stream the output audio to a destination.","example":null,"default":null,"anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"audio_frequency":{"description":"The audio frequency in Hz. Supported values: 24000 (default), 32000, 48000 Hz.","example":null,"default":24000,"anyOf":[{"description":"Audio frequency in Hz. Supported values: 16000, 24000 (default), 32000, 48000 Hz.","anyOf":[{"type":"number","const":16000},{"type":"number","const":24000},{"type":"number","const":32000},{"type":"number","const":48000}]},{"type":"null"}]}},"required":["input_url","output_url","audio_frequency"],"additionalProperties":false},{"type":"null"}]},"transcription_enabled":{"description":"Enable transcription for this bot. When enabled, the transcription_config property is used to customise the transcription provider and parameters.","default":false,"type":"boolean"},"transcription_config":{"default":null,"anyOf":[{"example":{"provider":"gladia","api_key":null,"custom_params":null},"type":"object","properties":{"provider":{"description":"The speech to text provider to use for the bot. The default and only supported provider is 'gladia'. More providers will be supported in the future.","default":"gladia","type":"string","enum":["gladia"]},"api_key":{"description":"The API key to use for the speech to text provider. This can be provided to use your own API key for the speech to text provider. It consumes less tokens than using the default API key. It is available on 'Pro' plans and above.","example":null,"default":null,"anyOf":[{"type":"string"},{"type":"null"}]},"custom_params":{"description":"Custom parameters for the transcription provider. See the transcription provider's documentation for available options. For Gladia, see https://docs.gladia.io/api-reference/v2/pre-recorded/init","example":null,"default":null,"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]}},"required":["provider","api_key","custom_params"],"additionalProperties":false},{"type":"null"}]},"callback_enabled":{"description":"Enable callback for this bot. When enabled, the callback_config property is used to provide the configuration.","default":false,"type":"boolean"},"callback_config":{"default":null,"anyOf":[{"example":null,"type":"object","properties":{"url":{"description":"The URL to be called upon the completion or failure of the bot.","type":"string","format":"uri"},"secret":{"description":"To ensure that you can validate the callback, this secret will be added to the request in the 'x-mb-secret' header","example":null,"default":null,"anyOf":[{"type":"string"},{"type":"null"}]},"method":{"description":"The HTTP method to use for the callback. Allowed values are 'POST' or 'PUT'.","default":"POST","type":"string","enum":["POST","PUT"]}},"required":["url","secret","method"],"additionalProperties":false},{"type":"null"}]},"join_at":{"description":"Update the scheduled join time.\n\nISO8601 format. Must be at least 4 minutes in the future and cannot be more than 90 days in the future.\n\nExample: \"2025-12-25T10:00:00Z\"","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"additionalProperties":false},"CreateScheduledBotResponse":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/CreateScheduledBotResponse","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"object","properties":{"bot_id":{"description":"The UUID of the created scheduled bot","type":"string","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)$"}},"required":["bot_id"],"additionalProperties":false}},"required":["success","data"],"additionalProperties":false},"BatchCreateScheduledBotResponse":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/BatchCreateScheduledBotResponse","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"description":"Scheduled bots that were successfully created","type":"array","items":{"type":"object","properties":{"index":{"description":"0-based index of the item in the request array","type":"integer","minimum":0,"maximum":9007199254740991},"bot_id":{"description":"The UUID of the created scheduled bot","type":"string","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)$"},"extra":{"description":"Custom metadata from the request (null if not provided)","anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]}},"required":["index","bot_id","extra"],"additionalProperties":false}},"errors":{"description":"Scheduled bots that failed to create (empty array if all succeeded)","type":"array","items":{"type":"object","properties":{"index":{"description":"0-based index of the item in the request array","type":"integer","minimum":0,"maximum":9007199254740991},"code":{"description":"Error code for programmatic handling","type":"string"},"message":{"description":"Human-readable error message","type":"string"},"details":{"description":"Additional error details (null if not available)","anyOf":[{"type":"string"},{"type":"null"}]},"extra":{"description":"Custom metadata from the request (null if not provided)","anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]}},"required":["index","code","message","details","extra"],"additionalProperties":false}}},"required":["success","data","errors"],"additionalProperties":false},"ListScheduledBotsResponse":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/ListScheduledBotsResponse","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"array","items":{"type":"object","properties":{"bot_id":{"description":"The UUID of the scheduled bot","type":"string","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)$"},"bot_name":{"description":"The name of the scheduled bot","type":"string"},"meeting_url":{"description":"The URL of the meeting","type":"string"},"meeting_platform":{"description":"The platform of the meeting","type":"string","enum":["zoom","meet","teams"]},"join_at":{"description":"ISO 8601 timestamp when the bot should join the meeting","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"status":{"description":"The current status of the scheduled bot","type":"string","enum":["scheduled","cancelled","completed","failed"]},"extra":{"description":"Custom metadata associated with the scheduled bot","anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]},"created_at":{"description":"ISO 8601 timestamp when the scheduled bot was created","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"updated_at":{"description":"ISO 8601 timestamp when the scheduled bot was last updated","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["bot_id","bot_name","meeting_url","meeting_platform","join_at","status","extra","created_at","updated_at"],"additionalProperties":false}},"cursor":{"description":"Cursor for the next page (null if no more pages)","anyOf":[{"type":"string"},{"type":"null"}]},"prev_cursor":{"description":"Cursor for the previous page (null if on first page)","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["success","data","cursor","prev_cursor"],"additionalProperties":false},"GetScheduledBotResponse":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/GetScheduledBotResponse","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"object","properties":{"bot_id":{"description":"The UUID of the scheduled bot","type":"string","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)$"},"bot_name":{"description":"The name of the scheduled bot","type":"string"},"bot_image":{"description":"The image URL for the bot (null if not set)","anyOf":[{"type":"string"},{"type":"null"}]},"meeting_url":{"description":"The URL of the meeting","type":"string"},"meeting_platform":{"description":"The platform of the meeting","type":"string","enum":["zoom","meet","teams"]},"recording_mode":{"description":"The recording mode for the bot","type":"string","enum":["audio_only","speaker_view","gallery_view"]},"join_at":{"description":"ISO 8601 timestamp when the bot should join the meeting","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"status":{"description":"The current status of the scheduled bot","type":"string","enum":["scheduled","cancelled","completed","failed"]},"created_at":{"description":"ISO 8601 timestamp when the scheduled bot was created","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"updated_at":{"description":"ISO 8601 timestamp when the scheduled bot was last updated","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"cancelled_at":{"description":"ISO 8601 timestamp when the scheduled bot was cancelled (null if not cancelled)","anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"allow_multiple_bots":{"description":"Whether multiple bots are allowed in the meeting","type":"boolean"},"entry_message":{"description":"Custom message to send when bot joins (null if not set)","anyOf":[{"type":"string"},{"type":"null"}]},"timeout_config":{"type":"object","properties":{"waiting_room_timeout":{"description":"Timeout in seconds for waiting room (null if not set)","anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"no_one_joined_timeout":{"description":"Timeout in seconds if no one joins (null if not set)","anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]}},"required":["waiting_room_timeout","no_one_joined_timeout"],"additionalProperties":false},"transcription_config":{"description":"Transcription configuration (null if transcription is disabled)","anyOf":[{"type":"object","properties":{"enabled":{"type":"boolean","const":true},"provider":{"type":"string","enum":["gladia"]},"custom_params":{"description":"Custom parameters for transcription (null if not set)","anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]}},"required":["enabled","provider","custom_params"],"additionalProperties":false},{"type":"null"}]},"streaming_config":{"description":"Streaming configuration (null if streaming is disabled)","anyOf":[{"type":"object","properties":{"enabled":{"type":"boolean","const":true},"input_url":{"description":"Websocket URL for receiving audio (null if not set)","anyOf":[{"type":"string"},{"type":"null"}]},"output_url":{"description":"Websocket URL for sending audio (null if not set)","anyOf":[{"type":"string"},{"type":"null"}]},"audio_frequency":{"description":"Audio frequency in Hz (null if not set). Supported values: 16000, 24000 (default), 32000, 48000 Hz.","anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]}},"required":["enabled","input_url","output_url","audio_frequency"],"additionalProperties":false},{"type":"null"}]},"callback_config":{"description":"Callback configuration (null if callback is disabled)","anyOf":[{"type":"object","properties":{"enabled":{"type":"boolean","const":true},"url":{"description":"Callback URL","type":"string"},"secret":{"description":"Secret for validating callbacks (null if not set)","anyOf":[{"type":"string"},{"type":"null"}]},"method":{"description":"HTTP method for callback","type":"string","enum":["POST","PUT"]}},"required":["enabled","url","secret","method"],"additionalProperties":false},{"type":"null"}]},"extra":{"description":"Custom metadata associated with the scheduled bot","anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]},"zoom_config":{"description":"Zoom configuration for this bot (null if not a Zoom bot or no zoom config provided)","anyOf":[{"type":"object","properties":{"credential_id":{"description":"UUID of the stored Zoom credential","anyOf":[{"type":"string","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":"null"}]},"credential_user_id":{"description":"Zoom user ID used to look up the credential","anyOf":[{"type":"string"},{"type":"null"}]},"obf_token_url":{"description":"URL that returns an OBF token at join time","anyOf":[{"type":"string"},{"type":"null"}]},"zak_token_url":{"description":"URL that returns a ZAK token at join time","anyOf":[{"type":"string"},{"type":"null"}]}},"additionalProperties":false},{"type":"null"}]}},"required":["bot_id","bot_name","bot_image","meeting_url","meeting_platform","recording_mode","join_at","status","created_at","updated_at","cancelled_at","allow_multiple_bots","entry_message","timeout_config","transcription_config","streaming_config","callback_config","extra","zoom_config"],"additionalProperties":false}},"required":["success","data"],"additionalProperties":false},"UpdateScheduledBotResponse":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/UpdateScheduledBotResponse","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"object","properties":{"message":{"description":"Success message","type":"string"}},"required":["message"],"additionalProperties":false}},"required":["success","data"],"additionalProperties":false},"DeleteScheduledBotResponse":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/DeleteScheduledBotResponse","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"object","properties":{"message":{"description":"Success message","type":"string"}},"required":["message"],"additionalProperties":false}},"required":["success","data"],"additionalProperties":false},"ListRawCalendarsRequestBody":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/ListRawCalendarsRequestBody","type":"object","properties":{"calendar_platform":{"description":"The calendar platform to connect to. Either 'google' for Google Calendar or 'microsoft' for Microsoft Outlook/365.","type":"string","enum":["google","microsoft"]},"oauth_client_id":{"description":"Your OAuth 2.0 client ID for the calendar platform.","type":"string","minLength":1},"oauth_client_secret":{"description":"Your OAuth 2.0 client secret for the calendar platform.","type":"string","minLength":1},"oauth_refresh_token":{"description":"The OAuth 2.0 refresh token obtained from the user's authorization. Must include 'offline_access' scope (Microsoft) or 'access_type=offline' (Google).","type":"string","minLength":1},"oauth_tenant_id":{"description":"Azure AD tenant ID (required for Microsoft only, defaults to 'common'). Find it in Azure Portal > Azure Active Directory > Overview. Example: '12345678-1234-1234-1234-123456789012'. You can also use 'common', 'organizations', or 'consumers' for multi-tenant scenarios.","default":"common","type":"string"}},"required":["calendar_platform","oauth_client_id","oauth_client_secret","oauth_refresh_token","oauth_tenant_id"],"additionalProperties":false},"CreateCalendarConnectionRequestBody":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/CreateCalendarConnectionRequestBody","type":"object","properties":{"calendar_platform":{"description":"The calendar platform to connect to. Either 'google' for Google Calendar or 'microsoft' for Microsoft Outlook/365.","type":"string","enum":["google","microsoft"]},"oauth_client_id":{"description":"Your OAuth 2.0 client ID for the calendar platform.","type":"string","minLength":1},"oauth_client_secret":{"description":"Your OAuth 2.0 client secret for the calendar platform.","type":"string","minLength":1},"oauth_refresh_token":{"description":"The OAuth 2.0 refresh token obtained from the user's authorization. Must include 'offline_access' scope (Microsoft) or 'access_type=offline' (Google).","type":"string","minLength":1},"oauth_tenant_id":{"description":"Azure AD tenant ID (required for Microsoft only, defaults to 'common'). Find it in Azure Portal > Azure Active Directory > Overview. Example: '12345678-1234-1234-1234-123456789012'. You can also use 'common', 'organizations', or 'consumers' for multi-tenant scenarios.","default":"common","type":"string"},"raw_calendar_id":{"description":"The specific calendar ID to connect. Use the 'List Raw Calendars' endpoint to get available calendar IDs. For Google, this is typically the calendar email (e.g., 'primary' or 'user@gmail.com'). For Microsoft, this is the calendar's unique identifier.","type":"string","minLength":1}},"required":["calendar_platform","oauth_client_id","oauth_client_secret","oauth_refresh_token","oauth_tenant_id","raw_calendar_id"],"additionalProperties":false},"UpdateCalendarConnectionRequestBody":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/UpdateCalendarConnectionRequestBody","type":"object","properties":{"oauth_client_id":{"description":"Your OAuth 2.0 client ID for the calendar platform.","type":"string","minLength":1},"oauth_client_secret":{"description":"Your OAuth 2.0 client secret for the calendar platform.","type":"string","minLength":1},"oauth_refresh_token":{"description":"The OAuth 2.0 refresh token obtained from the user's authorization. Must include 'offline_access' scope (Microsoft) or 'access_type=offline' (Google).","type":"string","minLength":1},"oauth_tenant_id":{"description":"Azure AD tenant ID (required for Microsoft only, defaults to 'common'). Find it in Azure Portal > Azure Active Directory > Overview. Example: '12345678-1234-1234-1234-123456789012'. You can also use 'common', 'organizations', or 'consumers' for multi-tenant scenarios.","default":"common","type":"string"}},"required":["oauth_client_id","oauth_client_secret","oauth_refresh_token","oauth_tenant_id"],"additionalProperties":false},"CreateCalendarBotRequestBody":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/CreateCalendarBotRequestBody","allOf":[{"type":"object","properties":{"bot_name":{"description":"The name of the bot.\n\nThis name will be displayed as the bot's name in the meeting.","example":"Meeting BaaS Bot","type":"string","minLength":1,"maxLength":255},"bot_image":{"description":"The bot's avatar image(s).\n\nAccepts a single HTTPS URL or an array of up to 5 HTTPS URLs pointing to image files (JPEG, PNG, or WebP). When multiple images are provided, they will be cycled based on the bot_image_config settings.","example":null,"default":null,"anyOf":[{"anyOf":[{"type":"string","format":"uri"},{"minItems":1,"maxItems":5,"type":"array","items":{"type":"string","format":"uri"}}]},{"type":"null"}]},"bot_image_config":{"description":"Configuration for how bot avatar images are displayed. Only relevant when multiple images are provided in bot_image.","example":null,"default":null,"anyOf":[{"type":"object","properties":{"loop_mode":{"description":"Controls how multiple bot images are cycled.\n\n- `auto`: Cycles through images at the interval specified by image_duration.\n- `bot_status`: Uses the first image when the bot joins, and the second image when recording starts. Only the first two images are used in this mode; additional images are ignored.","default":"auto","type":"string","enum":["auto","bot_status"]},"image_duration":{"description":"Duration in seconds each image is displayed before switching to the next. Only used when loop_mode is 'auto'.\n\nDefault: 30. Range: 10-120.","default":30,"type":"integer","minimum":10,"maximum":120}},"required":["loop_mode","image_duration"],"additionalProperties":false},{"type":"null"}]},"recording_mode":{"description":"The recording mode of the bot.\n\nDetermines what the bot records during the meeting:\n\n- `speaker_view`: Records the speaker's view (default). Shows the active speaker or presenter.\n- `audio_only`: Records only the audio without video.\n- `gallery_view`: Records the entire gallery view (coming soon).\n\nDefault: `speaker_view`","example":"speaker_view","default":"speaker_view","type":"string","enum":["audio_only","speaker_view","gallery_view"]},"entry_message":{"description":"The message that the bot will send when it joins the meeting.\n\nThis message will be posted in the meeting chat when the bot successfully joins.\n\nAvailable for Google Meet, Microsoft Teams, and Zoom meetings.\n\nMaximum: 500 characters","example":"Hello! I'm here to record this meeting.","default":null,"anyOf":[{"type":"string","maxLength":500},{"type":"null"}]},"timeout_config":{"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.","default":{"waiting_room_timeout":600,"no_one_joined_timeout":600,"silence_timeout":600},"type":"object","properties":{"waiting_room_timeout":{"description":"The timeout in seconds for the bot to wait in the waiting room before leaving the meeting.\n\nIf the bot is placed in a waiting room and not admitted within this time, it will leave the meeting.\n\nNote: Google Meet has its own waiting room timeout (approximately 10 minutes). Setting a higher value for Google Meet meetings will have no effect, as Google Meet will deny entry to the bot after its own timeout.\n\nDefault: 600 seconds (10 minutes)\nMinimum: 2 minutes\nMaximum: 30 minutes","example":600,"default":600,"type":"integer","minimum":120,"maximum":1800},"no_one_joined_timeout":{"description":"The timeout in seconds for the bot to wait for participants to join before leaving the meeting.\n\nIf no participants join the meeting within this time after the bot joins, the bot will leave the meeting. Only applicable for Google Meet and Microsoft Teams meetings.\n\nDefault: 600 seconds (10 minutes)\nMinimum: 2 minutes\nMaximum: 30 minutes","example":600,"default":600,"type":"integer","minimum":120,"maximum":1800},"silence_timeout":{"description":"The timeout in seconds for the bot to wait for silence before leaving the meeting.\n\nIf no audio is detected for this duration after the bot joins, the bot will leave the meeting. Only applicable for Google Meet and Microsoft Teams meetings.\n\nDefault: 600 seconds (10 minutes)\nMinimum: 5 minutes\nMaximum: 30 minutes","example":600,"default":600,"type":"integer","minimum":300,"maximum":1800}},"required":["waiting_room_timeout","no_one_joined_timeout","silence_timeout"],"additionalProperties":false},"zoom_config":{"description":"Zoom-only configuration for authentication and join method.\n\n- **credential_id**: Use a stored Zoom credential (OBF token fetched by the bot from the API server).\n- **credential_user_id**: Resolve a stored credential by Zoom user ID.\n- **obf_token**: Provide a direct OBF token (one-off join).\n- **obf_token_url**: URL that returns an OBF token when the bot joins.\n- **zak_token_url**: URL that returns a ZAK for joining without the host.\n\nLeave `null` for Google Meet and Microsoft Teams.","example":null,"default":null,"anyOf":[{"type":"object","properties":{"credential_id":{"description":"UUID of a stored Zoom credential (created via Zoom credentials API). The bot will fetch the OBF token from the API server using this ID. Use this when you have saved a Zoom OAuth credential and want the bot to join on behalf of that user.","type":"string","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)$"},"credential_user_id":{"description":"Zoom user ID (e.g. from the Zoom profile) to look up a stored credential by user. The API server will resolve this to a credential_id. Use when you have multiple credentials and want to target a specific user.","type":"string"},"obf_token":{"description":"Direct OBF (On-Behalf-Of) token. Use this to join a Zoom meeting as a specific user without storing a credential. The token is a JWT issued by Zoom; the bot uses it once to join. Suitable for short-lived or one-off joins. For recurring use, prefer credential_id or obf_token_url.","type":"string"},"obf_token_url":{"description":"URL that returns an OBF token at join time. The bot will make a GET request with query params: bot_uuid (bot UUID) and extra (URL-encoded JSON of the run's extra payload). Use these to identify which bot/run is requesting the token. Response must be plain text (ASCII) containing the OBF token. Timeout: 15 seconds.","type":"string","format":"uri"},"zak_token_url":{"description":"URL to get the Zoom ZAK (Zoom Access Token). The bot makes a GET request with query params: bot_uuid and extra (URL-encoded JSON). Use these to identify which bot/run is requesting the token. Response must be plain text (ASCII) with the raw ZAK. See https://developers.zoom.us/docs/api/users/#tag/users/get/users/me/zak. Timeout: 15 seconds.","type":"string","format":"uri"}},"additionalProperties":false},{"type":"null"}]},"extra":{"description":"An optional extra configuration object for the bot.\n\nThis object can contain any custom key-value pairs that you want to associate with the bot. The data will be:\n\n- Included in all webhook event payloads (if a webhook endpoint is configured)\n- Part of the callback payload (if callback is enabled)\n- Returned when fetching the bot's details via the API\n\nUseful for storing custom metadata, tracking information, or any other data you need to correlate with the bot.","example":null,"default":null,"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]},"streaming_enabled":{"description":"Enable audio streaming for this bot. When enabled, the streaming_config property is used to provide the configuration.","default":false,"type":"boolean"},"streaming_config":{"default":null,"anyOf":[{"example":null,"type":"object","properties":{"input_url":{"description":"Websocket stream URL, which receives the audio sent to the bot, and the bot will stream the audio to the meeting.","example":null,"default":null,"anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"output_url":{"description":"Websocket stream URL, which the bot sends the audio to. This is used to stream the output audio to a destination.","example":null,"default":null,"anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"audio_frequency":{"description":"The audio frequency in Hz. Supported values: 24000 (default), 32000, 48000 Hz.","example":null,"default":24000,"anyOf":[{"description":"Audio frequency in Hz. Supported values: 16000, 24000 (default), 32000, 48000 Hz.","anyOf":[{"type":"number","const":16000},{"type":"number","const":24000},{"type":"number","const":32000},{"type":"number","const":48000}]},{"type":"null"}]}},"required":["input_url","output_url","audio_frequency"],"additionalProperties":false},{"type":"null"}]},"transcription_enabled":{"description":"Enable transcription for this bot. When enabled, the transcription_config property is used to customise the transcription provider and parameters.","default":false,"type":"boolean"},"transcription_config":{"default":null,"anyOf":[{"example":{"provider":"gladia","api_key":null,"custom_params":null},"type":"object","properties":{"provider":{"description":"The speech to text provider to use for the bot. The default and only supported provider is 'gladia'. More providers will be supported in the future.","default":"gladia","type":"string","enum":["gladia"]},"api_key":{"description":"The API key to use for the speech to text provider. This can be provided to use your own API key for the speech to text provider. It consumes less tokens than using the default API key. It is available on 'Pro' plans and above.","example":null,"default":null,"anyOf":[{"type":"string"},{"type":"null"}]},"custom_params":{"description":"Custom parameters for the transcription provider. See the transcription provider's documentation for available options. For Gladia, see https://docs.gladia.io/api-reference/v2/pre-recorded/init","example":null,"default":null,"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]}},"required":["provider","api_key","custom_params"],"additionalProperties":false},{"type":"null"}]},"callback_enabled":{"description":"Enable callback for this bot. When enabled, the callback_config property is used to provide the configuration.","default":false,"type":"boolean"},"callback_config":{"default":null,"anyOf":[{"example":null,"type":"object","properties":{"url":{"description":"The URL to be called upon the completion or failure of the bot.","type":"string","format":"uri"},"secret":{"description":"To ensure that you can validate the callback, this secret will be added to the request in the 'x-mb-secret' header","example":null,"default":null,"anyOf":[{"type":"string"},{"type":"null"}]},"method":{"description":"The HTTP method to use for the callback. Allowed values are 'POST' or 'PUT'.","default":"POST","type":"string","enum":["POST","PUT"]}},"required":["url","secret","method"],"additionalProperties":false},{"type":"null"}]}},"required":["bot_name","bot_image","bot_image_config","recording_mode","entry_message","timeout_config","zoom_config","extra","streaming_enabled","streaming_config","transcription_enabled","transcription_config","callback_enabled","callback_config"],"additionalProperties":false},{"type":"object","properties":{"series_id":{"description":"The UUID of the event series to schedule bots for.\n\nBoth one-off and recurring events have a series_id. For recurring events, use 'all_occurrences' to schedule bots for all future occurrences.","type":"string","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)$"},"all_occurrences":{"description":"Whether to schedule bots for all occurrences of the event series.\n\nIf `true`, bots will be scheduled for all future event instances in the series. If `false`, `event_id` must be provided to schedule a bot for a specific event instance.\n\nDefault: `false`","default":false,"type":"boolean"},"event_id":{"description":"The UUID of a specific event instance to schedule a bot for.\n\nRequired when `all_occurrences` is `false`. Use this to schedule a bot for a single occurrence of a recurring event or a specific one-off event. If `all_occurrences` is `true`, this parameter is ignored.","example":null,"type":"string","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)$"}},"required":["series_id","all_occurrences"],"additionalProperties":false}]},"UpdateCalendarBotRequestBody":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/UpdateCalendarBotRequestBody","allOf":[{"type":"object","properties":{"series_id":{"description":"The UUID of the event series to schedule bots for.\n\nBoth one-off and recurring events have a series_id. For recurring events, use 'all_occurrences' to schedule bots for all future occurrences.","type":"string","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)$"},"all_occurrences":{"description":"Whether to schedule bots for all occurrences of the event series.\n\nIf `true`, bots will be scheduled for all future event instances in the series. If `false`, `event_id` must be provided to schedule a bot for a specific event instance.\n\nDefault: `false`","default":false,"type":"boolean"},"event_id":{"description":"The UUID of a specific event instance to schedule a bot for.\n\nRequired when `all_occurrences` is `false`. Use this to schedule a bot for a single occurrence of a recurring event or a specific one-off event. If `all_occurrences` is `true`, this parameter is ignored.","example":null,"type":"string","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)$"}},"required":["series_id","all_occurrences"],"additionalProperties":false},{"description":"Partial update of bot configuration. Only provide the fields you want to update. All fields are optional.","type":"object","properties":{"bot_name":{"description":"The name of the bot.\n\nThis name will be displayed as the bot's name in the meeting.","example":"Meeting BaaS Bot","type":"string","minLength":1,"maxLength":255},"bot_image":{"description":"The bot's avatar image(s).\n\nAccepts a single HTTPS URL or an array of up to 5 HTTPS URLs pointing to image files (JPEG, PNG, or WebP). When multiple images are provided, they will be cycled based on the bot_image_config settings.","example":null,"default":null,"anyOf":[{"anyOf":[{"type":"string","format":"uri"},{"minItems":1,"maxItems":5,"type":"array","items":{"type":"string","format":"uri"}}]},{"type":"null"}]},"bot_image_config":{"description":"Configuration for how bot avatar images are displayed. Only relevant when multiple images are provided in bot_image.","example":null,"default":null,"anyOf":[{"type":"object","properties":{"loop_mode":{"description":"Controls how multiple bot images are cycled.\n\n- `auto`: Cycles through images at the interval specified by image_duration.\n- `bot_status`: Uses the first image when the bot joins, and the second image when recording starts. Only the first two images are used in this mode; additional images are ignored.","default":"auto","type":"string","enum":["auto","bot_status"]},"image_duration":{"description":"Duration in seconds each image is displayed before switching to the next. Only used when loop_mode is 'auto'.\n\nDefault: 30. Range: 10-120.","default":30,"type":"integer","minimum":10,"maximum":120}},"required":["loop_mode","image_duration"],"additionalProperties":false},{"type":"null"}]},"recording_mode":{"description":"The recording mode of the bot.\n\nDetermines what the bot records during the meeting:\n\n- `speaker_view`: Records the speaker's view (default). Shows the active speaker or presenter.\n- `audio_only`: Records only the audio without video.\n- `gallery_view`: Records the entire gallery view (coming soon).\n\nDefault: `speaker_view`","example":"speaker_view","default":"speaker_view","type":"string","enum":["audio_only","speaker_view","gallery_view"]},"entry_message":{"description":"The message that the bot will send when it joins the meeting.\n\nThis message will be posted in the meeting chat when the bot successfully joins.\n\nAvailable for Google Meet, Microsoft Teams, and Zoom meetings.\n\nMaximum: 500 characters","example":"Hello! I'm here to record this meeting.","default":null,"anyOf":[{"type":"string","maxLength":500},{"type":"null"}]},"timeout_config":{"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.","default":{"waiting_room_timeout":600,"no_one_joined_timeout":600,"silence_timeout":600},"type":"object","properties":{"waiting_room_timeout":{"description":"The timeout in seconds for the bot to wait in the waiting room before leaving the meeting.\n\nIf the bot is placed in a waiting room and not admitted within this time, it will leave the meeting.\n\nNote: Google Meet has its own waiting room timeout (approximately 10 minutes). Setting a higher value for Google Meet meetings will have no effect, as Google Meet will deny entry to the bot after its own timeout.\n\nDefault: 600 seconds (10 minutes)\nMinimum: 2 minutes\nMaximum: 30 minutes","example":600,"default":600,"type":"integer","minimum":120,"maximum":1800},"no_one_joined_timeout":{"description":"The timeout in seconds for the bot to wait for participants to join before leaving the meeting.\n\nIf no participants join the meeting within this time after the bot joins, the bot will leave the meeting. Only applicable for Google Meet and Microsoft Teams meetings.\n\nDefault: 600 seconds (10 minutes)\nMinimum: 2 minutes\nMaximum: 30 minutes","example":600,"default":600,"type":"integer","minimum":120,"maximum":1800},"silence_timeout":{"description":"The timeout in seconds for the bot to wait for silence before leaving the meeting.\n\nIf no audio is detected for this duration after the bot joins, the bot will leave the meeting. Only applicable for Google Meet and Microsoft Teams meetings.\n\nDefault: 600 seconds (10 minutes)\nMinimum: 5 minutes\nMaximum: 30 minutes","example":600,"default":600,"type":"integer","minimum":300,"maximum":1800}},"required":["waiting_room_timeout","no_one_joined_timeout","silence_timeout"],"additionalProperties":false},"zoom_config":{"description":"Zoom-only configuration for authentication and join method.\n\n- **credential_id**: Use a stored Zoom credential (OBF token fetched by the bot from the API server).\n- **credential_user_id**: Resolve a stored credential by Zoom user ID.\n- **obf_token**: Provide a direct OBF token (one-off join).\n- **obf_token_url**: URL that returns an OBF token when the bot joins.\n- **zak_token_url**: URL that returns a ZAK for joining without the host.\n\nLeave `null` for Google Meet and Microsoft Teams.","example":null,"default":null,"anyOf":[{"type":"object","properties":{"credential_id":{"description":"UUID of a stored Zoom credential (created via Zoom credentials API). The bot will fetch the OBF token from the API server using this ID. Use this when you have saved a Zoom OAuth credential and want the bot to join on behalf of that user.","type":"string","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)$"},"credential_user_id":{"description":"Zoom user ID (e.g. from the Zoom profile) to look up a stored credential by user. The API server will resolve this to a credential_id. Use when you have multiple credentials and want to target a specific user.","type":"string"},"obf_token":{"description":"Direct OBF (On-Behalf-Of) token. Use this to join a Zoom meeting as a specific user without storing a credential. The token is a JWT issued by Zoom; the bot uses it once to join. Suitable for short-lived or one-off joins. For recurring use, prefer credential_id or obf_token_url.","type":"string"},"obf_token_url":{"description":"URL that returns an OBF token at join time. The bot will make a GET request with query params: bot_uuid (bot UUID) and extra (URL-encoded JSON of the run's extra payload). Use these to identify which bot/run is requesting the token. Response must be plain text (ASCII) containing the OBF token. Timeout: 15 seconds.","type":"string","format":"uri"},"zak_token_url":{"description":"URL to get the Zoom ZAK (Zoom Access Token). The bot makes a GET request with query params: bot_uuid and extra (URL-encoded JSON). Use these to identify which bot/run is requesting the token. Response must be plain text (ASCII) with the raw ZAK. See https://developers.zoom.us/docs/api/users/#tag/users/get/users/me/zak. Timeout: 15 seconds.","type":"string","format":"uri"}},"additionalProperties":false},{"type":"null"}]},"extra":{"description":"An optional extra configuration object for the bot.\n\nThis object can contain any custom key-value pairs that you want to associate with the bot. The data will be:\n\n- Included in all webhook event payloads (if a webhook endpoint is configured)\n- Part of the callback payload (if callback is enabled)\n- Returned when fetching the bot's details via the API\n\nUseful for storing custom metadata, tracking information, or any other data you need to correlate with the bot.","example":null,"default":null,"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]},"streaming_enabled":{"description":"Enable or disable audio streaming for this bot.\n\n- Set to `true` to enable streaming (requires `streaming_config`)\n- Set to `false` to disable streaming (do not provide `streaming_config`)\n- Omit this field to leave streaming configuration unchanged\n\nIf you want to change streaming settings, you must provide both `streaming_enabled` and `streaming_config` together.","type":"boolean"},"streaming_config":{"description":"The streaming configuration for the bot.\n\nRequired when `streaming_enabled` is `true`. Must not be provided when `streaming_enabled` is `false`.\n\n- `input_url`: Websocket stream URL that receives audio sent to the bot\n- `output_url`: Websocket stream URL where the bot sends audio\n- `audio_frequency`: Audio frequency in Hz (default: 24000)\n\nOmit this field to leave streaming configuration unchanged.","example":null,"type":"object","properties":{"input_url":{"description":"Websocket stream URL, which receives the audio sent to the bot, and the bot will stream the audio to the meeting.","example":null,"default":null,"anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"output_url":{"description":"Websocket stream URL, which the bot sends the audio to. This is used to stream the output audio to a destination.","example":null,"default":null,"anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"audio_frequency":{"description":"The audio frequency in Hz. Supported values: 24000 (default), 32000, 48000 Hz.","example":null,"default":24000,"anyOf":[{"description":"Audio frequency in Hz. Supported values: 16000, 24000 (default), 32000, 48000 Hz.","anyOf":[{"type":"number","const":16000},{"type":"number","const":24000},{"type":"number","const":32000},{"type":"number","const":48000}]},{"type":"null"}]}},"required":["input_url","output_url","audio_frequency"],"additionalProperties":false},"transcription_enabled":{"description":"Enable or disable transcription for this bot.\n\n- Set to `true` to enable transcription (requires `transcription_config`)\n- Set to `false` to disable transcription (do not provide `transcription_config`)\n- Omit this field to leave transcription configuration unchanged\n\nIf you want to change transcription settings, you must provide both `transcription_enabled` and `transcription_config` together.","type":"boolean"},"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\")\n- `api_key`: Your own API key for the provider (BYOK - available on Pro plans and above)\n- `custom_params`: Custom parameters for transcription (see Gladia API documentation)\n\nOmit this field to leave transcription configuration unchanged.","example":{"provider":"gladia","api_key":null,"custom_params":null},"type":"object","properties":{"provider":{"description":"The speech to text provider to use for the bot. The default and only supported provider is 'gladia'. More providers will be supported in the future.","default":"gladia","type":"string","enum":["gladia"]},"api_key":{"description":"The API key to use for the speech to text provider. This can be provided to use your own API key for the speech to text provider. It consumes less tokens than using the default API key. It is available on 'Pro' plans and above.","example":null,"default":null,"anyOf":[{"type":"string"},{"type":"null"}]},"custom_params":{"description":"Custom parameters for the transcription provider. See the transcription provider's documentation for available options. For Gladia, see https://docs.gladia.io/api-reference/v2/pre-recorded/init","example":null,"default":null,"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]}},"required":["provider","api_key","custom_params"],"additionalProperties":false},"callback_enabled":{"description":"Enable or disable callback for this bot.\n\n- Set to `true` to enable callback (requires `callback_config`)\n- Set to `false` to disable callback (do not provide `callback_config`)\n- Omit this field to leave callback configuration unchanged\n\nIf you want to change callback settings, you must provide both `callback_enabled` and `callback_config` together.","type":"boolean"},"callback_config":{"description":"The callback configuration for the bot.\n\nRequired when `callback_enabled` is `true`. Must not be provided when `callback_enabled` is `false`.\n\n- `url`: The URL to be called upon completion or failure of the bot\n- `secret`: Secret for HMAC validation (sent in `x-mb-secret` header)\n- `method`: HTTP method (`POST` or `PUT`, default: `POST`)\n\nOmit this field to leave callback configuration unchanged.","example":null,"type":"object","properties":{"url":{"description":"The URL to be called upon the completion or failure of the bot.","type":"string","format":"uri"},"secret":{"description":"To ensure that you can validate the callback, this secret will be added to the request in the 'x-mb-secret' header","example":null,"default":null,"anyOf":[{"type":"string"},{"type":"null"}]},"method":{"description":"The HTTP method to use for the callback. Allowed values are 'POST' or 'PUT'.","default":"POST","type":"string","enum":["POST","PUT"]}},"required":["url","secret","method"],"additionalProperties":false}},"additionalProperties":false}]},"ListRawCalendarsResponse":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/ListRawCalendarsResponse","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"array","items":{"type":"object","properties":{"id":{"description":"The calendar ID from the calendar platform. Use this value as the 'raw_calendar_id' parameter when creating a calendar connection","type":"string"},"name":{"description":"The display name of the calendar as shown in the calendar application","type":"string"},"email":{"description":"The email address associated with the calendar. For Google Calendar, this is typically the calendar owner's email. For Microsoft, this is the calendar's email address","type":"string"},"is_primary":{"description":"Whether this is the user's primary/default calendar. The primary calendar is typically the main calendar associated with the user's account","type":"boolean"}},"required":["id","name","email","is_primary"],"additionalProperties":false}}},"required":["success","data"],"additionalProperties":false},"CreateCalendarConnectionResponse":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/CreateCalendarConnectionResponse","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"object","properties":{"calendar_id":{"description":"The UUID of the newly created calendar connection. Use this ID to reference the calendar in other API endpoints","type":"string","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)$"},"calendar_platform":{"description":"The calendar platform where this connection was established. Either 'google' for Google Calendar or 'microsoft' for Microsoft Outlook/365","type":"string","enum":["google","microsoft"]},"account_email":{"description":"The email address associated with the calendar account. This is the email of the calendar owner","type":"string"},"status":{"description":"The current status of the calendar connection. Possible values: 'active' (connection is working), 'error' (connection has errors), 'revoked' (OAuth access was revoked), 'permission_denied' (insufficient permissions)","type":"string","enum":["active","error","revoked","permission_denied"]},"created_at":{"description":"ISO 8601 timestamp when the calendar connection was created and synced","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["calendar_id","calendar_platform","account_email","status","created_at"],"additionalProperties":false}},"required":["success","data"],"additionalProperties":false},"ListCalendarsResponse":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/ListCalendarsResponse","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"array","items":{"type":"object","properties":{"calendar_id":{"description":"The UUID of the calendar connection. Use this ID to reference the calendar in other API endpoints","type":"string","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)$"},"calendar_platform":{"description":"The calendar platform. Either 'google' for Google Calendar or 'microsoft' for Microsoft Outlook/365","type":"string","enum":["google","microsoft"]},"account_email":{"description":"The email address associated with the calendar account. This is the email of the calendar owner","type":"string"},"status":{"description":"The current status of the calendar connection. Possible values: 'active' (connection is working), 'error' (connection has errors), 'revoked' (OAuth access was revoked), 'permission_denied' (insufficient permissions)","type":"string","enum":["active","error","revoked","permission_denied"]},"synced_at":{"description":"ISO 8601 timestamp of the last successful calendar sync. Null if the calendar has never been synced yet. Syncs happen automatically when events change, or can be triggered manually using the sync endpoint","anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"created_at":{"description":"ISO 8601 timestamp when the calendar connection was created and initially synced","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["calendar_id","calendar_platform","account_email","status","synced_at","created_at"],"additionalProperties":false}},"cursor":{"description":"Cursor for the next page (null if no more pages)","anyOf":[{"type":"string"},{"type":"null"}]},"prev_cursor":{"description":"Cursor for the previous page (null if on first page)","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["success","data","cursor","prev_cursor"],"additionalProperties":false},"GetCalendarDetailsResponse":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/GetCalendarDetailsResponse","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"object","properties":{"calendar_id":{"description":"The UUID of the calendar connection. Use this ID to reference the calendar in other API endpoints","type":"string","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)$"},"calendar_platform":{"description":"The calendar platform. Either 'google' for Google Calendar or 'microsoft' for Microsoft Outlook/365","type":"string","enum":["google","microsoft"]},"account_email":{"description":"The email address associated with the calendar account. This is the email of the calendar owner","type":"string"},"status":{"description":"The current status of the calendar connection. Possible values: 'active' (connection is working), 'error' (connection has errors), 'revoked' (OAuth access was revoked), 'permission_denied' (insufficient permissions)","type":"string","enum":["active","error","revoked","permission_denied"]},"status_message":{"description":"A human-readable message providing additional context about the connection status. Null if there is no additional status message to display","anyOf":[{"type":"string"},{"type":"null"}]},"subscription_id":{"description":"The subscription ID assigned by the calendar provider (Google or Microsoft). This ID is used to manage the webhook subscription. Null if no subscription exists","anyOf":[{"type":"string"},{"type":"null"}]},"subscription_expires_at":{"description":"ISO 8601 timestamp when the webhook subscription expires. Subscriptions typically expire after a certain period (e.g., 7 days for Google, 3 days for Microsoft) and need to be renewed. Null if no subscription exists","anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"synced_at":{"description":"ISO 8601 timestamp of the last successful calendar sync. Null if the calendar has never been synced. Syncs fetch events from the calendar platform and update the local database","anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"sync_status":{"description":"The status of the last sync operation. Null if no sync has been performed yet. Possible values when not null: 'success' (sync completed successfully), 'failed' (sync failed completely), 'partial' (sync completed but some events could not be processed)","anyOf":[{"type":"string","enum":["success","failed","partial"]},{"type":"null"}]},"sync_error":{"description":"Error message from the last sync operation if it failed. This provides details about what went wrong during the sync. Null if the last sync was successful or if no sync has been performed","anyOf":[{"type":"string"},{"type":"null"}]},"provider_metadata":{"description":"Additional metadata returned by the calendar provider about this calendar. This may include calendar-specific settings, permissions, or other platform-specific information. Null if the provider did not return metadata or if metadata is not available","anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]},"created_at":{"description":"ISO 8601 timestamp when the calendar connection was created and initially synced","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"updated_at":{"description":"ISO 8601 timestamp when the calendar connection was last updated. This updates when connection settings change, credentials are refreshed, or subscription details are updated","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["calendar_id","calendar_platform","account_email","status","status_message","subscription_id","subscription_expires_at","synced_at","sync_status","sync_error","provider_metadata","created_at","updated_at"],"additionalProperties":false}},"required":["success","data"],"additionalProperties":false},"UpdateCalendarConnectionResponse":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/UpdateCalendarConnectionResponse","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"object","properties":{"calendar_id":{"description":"The UUID of the updated calendar connection. Use this ID to reference the calendar in other API endpoints","type":"string","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)$"},"calendar_platform":{"description":"The calendar platform. Either 'google' for Google Calendar or 'microsoft' for Microsoft Outlook/365","type":"string","enum":["google","microsoft"]},"account_email":{"description":"The email address associated with the calendar account. This is the email of the calendar owner","type":"string"},"status":{"description":"The current status of the calendar connection after the update. Possible values: 'active' (connection is working), 'error' (connection has errors), 'revoked' (OAuth access was revoked), 'permission_denied' (insufficient permissions)","type":"string","enum":["active","error","revoked","permission_denied"]},"updated_at":{"description":"ISO 8601 timestamp when the calendar connection was last updated with the new credentials or settings","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["calendar_id","calendar_platform","account_email","status","updated_at"],"additionalProperties":false}},"required":["success","data"],"additionalProperties":false},"DeleteCalendarConnectionResponse":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/DeleteCalendarConnectionResponse","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"object","properties":{"message":{"description":"Success message confirming that the calendar connection has been deleted. All associated event instances, series, and bot schedules have also been removed","type":"string"}},"required":["message"],"additionalProperties":false}},"required":["success","data"],"additionalProperties":false},"SyncCalendarResponse":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/SyncCalendarResponse","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"object","properties":{"message":{"description":"Success message confirming that the calendar sync operation has been initiated. The sync will fetch the latest events from the calendar platform and update the local database","type":"string"}},"required":["message"],"additionalProperties":false}},"required":["success","data"],"additionalProperties":false},"ResubscribeCalendarResponse":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/ResubscribeCalendarResponse","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"object","properties":{"calendar_id":{"description":"The UUID of the calendar connection that was resubscribed. Use this ID to reference the calendar in other API endpoints","type":"string","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)$"},"resubscribed_at":{"description":"ISO 8601 timestamp when the calendar connection was resubscribed","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["calendar_id","resubscribed_at"],"additionalProperties":false}},"required":["success","data"],"additionalProperties":false},"ListEventsResponse":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/ListEventsResponse","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"array","items":{"type":"object","properties":{"series_id":{"description":"The UUID of the event series this instance belongs to. Every event instance (both one-off and recurring) is associated with a series. Use this ID when scheduling bots for all occurrences of a recurring series","type":"string","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)$"},"event_type":{"description":"The type of event. 'one_off' for single events that occur once, 'recurring' for events that are part of a recurring series with multiple occurrences","type":"string","enum":["one_off","recurring"]},"event_id":{"description":"The UUID of the event instance","type":"string","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)$"},"title":{"description":"The title of the event","type":"string"},"start_time":{"description":"ISO 8601 timestamp when the event starts","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"end_time":{"description":"ISO 8601 timestamp when the event ends","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"status":{"description":"The status of the event. Possible values: 'confirmed' (event is confirmed), 'cancelled' (event has been cancelled), 'tentative' (event is tentative)","type":"string","enum":["confirmed","cancelled","tentative"]},"is_exception":{"description":"Whether this is an exception to a recurring series. True if this instance has been modified differently from the recurring pattern","type":"boolean"},"meeting_url":{"description":"The meeting URL extracted from the event. Null if the calendar platform did not include a meeting link in the event","anyOf":[{"type":"string"},{"type":"null"}]},"meeting_platform":{"description":"The meeting platform detected from the meeting URL. Null if no meeting link was found in the event. Possible values: 'zoom', 'meet', or 'teams'","anyOf":[{"type":"string","enum":["zoom","meet","teams"]},{"type":"null"}]},"calendar_id":{"description":"The UUID of the calendar connection this event belongs to","type":"string","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)$"},"bot_scheduled":{"description":"Whether a bot has been scheduled for this event instance. True if a calendar bot schedule exists for this event","type":"boolean"},"created_at":{"description":"ISO 8601 timestamp when this event instance was first synced into the system","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["series_id","event_type","event_id","title","start_time","end_time","status","is_exception","meeting_url","meeting_platform","calendar_id","bot_scheduled","created_at"],"additionalProperties":false}},"cursor":{"description":"Cursor for the next page (null if no more pages)","anyOf":[{"type":"string"},{"type":"null"}]},"prev_cursor":{"description":"Cursor for the previous page (null if on first page)","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["success","data","cursor","prev_cursor"],"additionalProperties":false},"ListEventSeriesResponse":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/ListEventSeriesResponse","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"array","items":{"type":"object","properties":{"series_id":{"description":"The UUID of the event series. Every event (both one-off and recurring) is associated with a series. Use this ID when scheduling bots for all occurrences of a recurring series","type":"string","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)$"},"event_type":{"description":"The type of event. 'one_off' for single events that occur once, 'recurring' for events that are part of a recurring series with multiple occurrences","type":"string","enum":["one_off","recurring"]},"calendar_id":{"description":"The UUID of the calendar connection this event series belongs to","type":"string","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)$"},"created_at":{"description":"ISO 8601 timestamp when this event series was first synced into the system","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"events":{"description":"List of event instances that belong to this series. For one-off events, this array contains a single instance. For recurring events, this array contains all instances that have been synced (typically within a 30-day window)","type":"array","items":{"type":"object","properties":{"event_id":{"description":"The UUID of the event instance","type":"string","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)$"},"title":{"description":"The title of the event","type":"string"},"start_time":{"description":"ISO 8601 timestamp when the event starts","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"end_time":{"description":"ISO 8601 timestamp when the event ends","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"status":{"description":"The status of the event. Possible values: 'confirmed' (event is confirmed), 'cancelled' (event has been cancelled), 'tentative' (event is tentative)","type":"string","enum":["confirmed","cancelled","tentative"]},"is_exception":{"description":"Whether this is an exception to a recurring series. True if this instance has been modified differently from the recurring pattern","type":"boolean"},"meeting_url":{"description":"The meeting URL extracted from the event. Null if the calendar platform did not include a meeting link in the event","anyOf":[{"type":"string"},{"type":"null"}]},"meeting_platform":{"description":"The meeting platform detected from the meeting URL. Null if no meeting link was found in the event. Possible values: 'zoom', 'meet', or 'teams'","anyOf":[{"type":"string","enum":["zoom","meet","teams"]},{"type":"null"}]},"calendar_id":{"description":"The UUID of the calendar connection this event belongs to","type":"string","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)$"},"bot_scheduled":{"description":"Whether a bot has been scheduled for this event instance. True if a calendar bot schedule exists for this event","type":"boolean"},"created_at":{"description":"ISO 8601 timestamp when this event instance was first synced into the system","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["event_id","title","start_time","end_time","status","is_exception","meeting_url","meeting_platform","calendar_id","bot_scheduled","created_at"],"additionalProperties":false}}},"required":["series_id","event_type","calendar_id","created_at","events"],"additionalProperties":false}},"cursor":{"description":"Cursor for the next page (null if no more pages)","anyOf":[{"type":"string"},{"type":"null"}]},"prev_cursor":{"description":"Cursor for the previous page (null if on first page)","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["success","data","cursor","prev_cursor"],"additionalProperties":false},"GetEventDetailsResponse":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/GetEventDetailsResponse","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"type":"object","properties":{"event_id":{"description":"The UUID of the event instance","type":"string","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)$"},"series_id":{"description":"The UUID of the event series this instance belongs to. Every event instance (both one-off and recurring) is associated with a series. Use this ID when scheduling bots for all occurrences of a recurring series","type":"string","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)$"},"event_type":{"description":"The type of event. 'one_off' for single events that occur once, 'recurring' for events that are part of a recurring series with multiple occurrences","type":"string","enum":["one_off","recurring"]},"title":{"description":"The title of the event as stored in the calendar","type":"string"},"description":{"description":"The description of the event as returned by the calendar platform. Null if the calendar platform did not include a description for this event","anyOf":[{"type":"string"},{"type":"null"}]},"location":{"description":"The location of the event as returned by the calendar platform. Null if the calendar platform did not include a location for this event","anyOf":[{"type":"string"},{"type":"null"}]},"start_time":{"description":"ISO 8601 timestamp when the event starts","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"end_time":{"description":"ISO 8601 timestamp when the event ends","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"timezone":{"description":"The IANA timezone identifier for the event (e.g., 'America/New_York', 'Europe/London'). Null if the calendar platform did not provide timezone information or if the event is all-day","anyOf":[{"type":"string"},{"type":"null"}]},"is_all_day":{"description":"Whether this is an all-day event. True if the event spans entire days without specific start/end times","type":"boolean"},"status":{"description":"The status of the event. Possible values: 'confirmed' (event is confirmed), 'cancelled' (event has been cancelled), 'tentative' (event is tentative)","type":"string","enum":["confirmed","cancelled","tentative"]},"organizer_email":{"description":"The email address of the event organizer as returned by the calendar platform. Null if the calendar platform did not provide organizer information","anyOf":[{"type":"string"},{"type":"null"}]},"organizer_name":{"description":"The display name of the event organizer as returned by the calendar platform. Null if the calendar platform did not provide organizer name information","anyOf":[{"type":"string"},{"type":"null"}]},"attendees":{"description":"List of event attendees as returned by the calendar platform. Null if the calendar platform did not provide attendee information or if the event has no attendees","anyOf":[{"type":"array","items":{"type":"object","properties":{"email":{"description":"The email address of the attendee","type":"string"},"name":{"description":"The display name of the attendee as returned by the calendar platform. Null if the calendar platform did not provide a display name for this attendee","anyOf":[{"type":"string"},{"type":"null"}]},"response_status":{"description":"The attendee's response status to the event invitation. Defaults to 'needsAction' if the calendar platform did not provide response status information. Possible values: 'accepted' (attendee accepted the invitation), 'declined' (attendee declined the invitation), 'tentative' (attendee responded as tentative), 'needsAction' (attendee has not responded yet)","type":"string","enum":["accepted","declined","tentative","needsAction"]},"organizer":{"description":"Whether this attendee is the organizer of the event. Only present if the calendar platform provides this information","type":"boolean"},"self":{"description":"Whether this attendee represents the authenticated user who owns the calendar connection. Only present if the calendar platform provides this information","type":"boolean"}},"required":["email","name","response_status"],"additionalProperties":false}},{"type":"null"}]},"meeting_url":{"description":"The meeting URL extracted from the event. Null if the calendar platform did not include a meeting link in the event","anyOf":[{"type":"string"},{"type":"null"}]},"meeting_platform":{"description":"The meeting platform detected from the meeting URL. Null if no meeting link was found in the event. Possible values: 'zoom', 'meet', or 'teams'","anyOf":[{"type":"string","enum":["zoom","meet","teams"]},{"type":"null"}]},"calendar_id":{"description":"The UUID of the calendar connection this event belongs to","type":"string","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)$"},"calendar_platform":{"description":"The calendar platform where this event originates. Either 'google' for Google Calendar or 'microsoft' for Microsoft Outlook/365","type":"string","enum":["google","microsoft"]},"bot_scheduled":{"description":"Whether a bot has been scheduled for this event instance. True if a calendar bot schedule exists for this event","type":"boolean"},"created_at":{"description":"ISO 8601 timestamp when this event instance was first synced into the system","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"updated_at":{"description":"ISO 8601 timestamp when this event instance was last updated (either from a sync or from a webhook notification)","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["event_id","series_id","event_type","title","description","location","start_time","end_time","timezone","is_all_day","status","organizer_email","organizer_name","attendees","meeting_url","meeting_platform","calendar_id","calendar_platform","bot_scheduled","created_at","updated_at"],"additionalProperties":false}},"required":["success","data"],"additionalProperties":false},"CreateCalendarBotResponse":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/CreateCalendarBotResponse","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"description":"Event instances that were successfully scheduled for bot recording or had their bots updated/deleted successfully","type":"array","items":{"type":"object","properties":{"event_id":{"description":"The UUID of the event instance that was successfully scheduled for bot recording","type":"string","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)$"}},"required":["event_id"],"additionalProperties":false}},"errors":{"description":"Array of errors for event instances that failed to schedule. This array is empty if all event instances were successfully scheduled. Each error object contains information about a specific event instance that could not be scheduled","type":"array","items":{"type":"object","properties":{"event_id":{"description":"The UUID of the event instance that failed to be scheduled. Use this to identify which specific event could not be scheduled","type":"string","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)$"},"code":{"description":"Error code for programmatic handling. This is a machine-readable identifier that indicates the type of error that occurred","type":"string"},"message":{"description":"Human-readable error message explaining why the scheduling failed for this event instance","type":"string"},"details":{"description":"Additional error details providing more context about the failure. Null if no additional details are available","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["event_id","code","message","details"],"additionalProperties":false}}},"required":["success","data","errors"],"additionalProperties":false},"UpdateCalendarBotResponse":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/UpdateCalendarBotResponse","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"description":"Event instances whose calendar bots were successfully updated","type":"array","items":{"type":"object","properties":{"event_id":{"description":"The UUID of the event instance that was successfully scheduled for bot recording","type":"string","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)$"}},"required":["event_id"],"additionalProperties":false}},"errors":{"description":"Array of errors for event instances whose calendar bots could not be updated. This array is empty if all requested event instances were successfully updated","type":"array","items":{"type":"object","properties":{"event_id":{"description":"The UUID of the event instance that failed to be scheduled. Use this to identify which specific event could not be scheduled","type":"string","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)$"},"code":{"description":"Error code for programmatic handling. This is a machine-readable identifier that indicates the type of error that occurred","type":"string"},"message":{"description":"Human-readable error message explaining why the scheduling failed for this event instance","type":"string"},"details":{"description":"Additional error details providing more context about the failure. Null if no additional details are available","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["event_id","code","message","details"],"additionalProperties":false}}},"required":["success","data","errors"],"additionalProperties":false},"DeleteCalendarBotResponse":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/DeleteCalendarBotResponse","type":"object","properties":{"success":{"type":"boolean","const":true},"data":{"description":"Event instances whose calendar bots were successfully deleted/cancelled","type":"array","items":{"type":"object","properties":{"event_id":{"description":"The UUID of the event instance that was successfully scheduled for bot recording","type":"string","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)$"}},"required":["event_id"],"additionalProperties":false}},"errors":{"description":"Array of errors for event instances whose calendar bots could not be deleted. This array is empty if all requested event instances were successfully deleted","type":"array","items":{"type":"object","properties":{"event_id":{"description":"The UUID of the event instance that failed to be scheduled. Use this to identify which specific event could not be scheduled","type":"string","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)$"},"code":{"description":"Error code for programmatic handling. This is a machine-readable identifier that indicates the type of error that occurred","type":"string"},"message":{"description":"Human-readable error message explaining why the scheduling failed for this event instance","type":"string"},"details":{"description":"Additional error details providing more context about the failure. Null if no additional details are available","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["event_id","code","message","details"],"additionalProperties":false}}},"required":["success","data","errors"],"additionalProperties":false},"BotWebhookStatusChange":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/BotWebhookStatusChange","type":"object","properties":{"event":{"description":"The webhook event type","type":"string","const":"bot.status_change"},"data":{"type":"object","properties":{"bot_id":{"description":"The UUID of the bot that changed status","type":"string","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)$"},"event_id":{"description":"The UUID of the calendar event associated with this bot. Null for non-calendar bots","anyOf":[{"type":"string","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":"null"}]},"status":{"description":"Status information with code, timestamp, and optional status-specific fields","type":"object","properties":{"code":{"description":"The status code (e.g., 'transcribing', 'recording', 'processing')","type":"string"},"created_at":{"description":"ISO 8601 timestamp when this status change occurred","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"start_time":{"description":"Unix timestamp (seconds) when recording started. Only present for 'in_call_recording' status","type":"integer","minimum":0,"maximum":9007199254740991},"error_message":{"description":"Error message describing what went wrong. Only present for 'recording_failed' status","type":"string"}},"required":["code","created_at"],"additionalProperties":false}},"required":["bot_id","event_id","status"],"additionalProperties":false},"extra":{"description":"Additional metadata provided when creating the bot. This is user-defined data that can be used for correlation or tracking","anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]}},"required":["event","data","extra"],"additionalProperties":false},"BotWebhookCompleted":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/CallbackCompleted","type":"object","properties":{"event":{"description":"The webhook event type","type":"string","const":"bot.completed"},"data":{"type":"object","properties":{"bot_id":{"description":"The UUID of the bot that completed","type":"string","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)$"},"event_id":{"description":"The UUID of the calendar event associated with this bot. Null for non-calendar bots","anyOf":[{"type":"string","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":"null"}]},"participants":{"description":"List of participants who joined the meeting with their names and metadata. Empty array if participant information is not available","type":"array","items":{"type":"object","properties":{"name":{"description":"Participant's name (full name or display name)","type":"string"},"id":{"description":"Sequential participant ID (1, 2, 3...). Null if not available","anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"display_name":{"description":"Display name shown in UI (if different from name)","type":"string"},"profile_picture":{"description":"Profile picture URL (if available)","type":"string","format":"uri"}},"required":["name","id"],"additionalProperties":false}},"speakers":{"description":"List of speakers detected in the meeting with their names and metadata. Empty array if speaker information is not available","type":"array","items":{"type":"object","properties":{"name":{"description":"Participant's name (full name or display name)","type":"string"},"id":{"description":"Sequential participant ID (1, 2, 3...). Null if not available","anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"display_name":{"description":"Display name shown in UI (if different from name)","type":"string"},"profile_picture":{"description":"Profile picture URL (if available)","type":"string","format":"uri"}},"required":["name","id"],"additionalProperties":false}},"duration_seconds":{"anyOf":[{"description":"The duration of the meeting in seconds. Null if duration could not be determined","type":"integer","minimum":0,"maximum":9007199254740991},{"type":"null"}]},"joined_at":{"description":"ISO 8601 timestamp when the bot joined the meeting. Null if join time is not available","anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"exited_at":{"description":"ISO 8601 timestamp when the bot exited the meeting. Null if exit time is not available","anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"data_deleted":{"description":"Whether the bot's data (artifacts, recordings) has been deleted. True if data has been permanently removed","type":"boolean"},"video":{"description":"Signed URL to download the video recording. Valid for 4 hours. Null if video recording is not available or has been deleted","anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"audio":{"description":"Signed URL to download the audio recording. Valid for 4 hours. Null if audio recording is not available or has been deleted","anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"diarization":{"description":"Signed URL to download the speaker diarization data. Valid for 4 hours. Null if diarization is not available or has been deleted","anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"raw_transcription":{"description":"Signed URL to download the raw transcription file. Valid for 4 hours. Null if raw transcription is not available or has been deleted","anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"transcription":{"description":"Signed URL to download the processed transcription file. Valid for 4 hours. Null if transcription is not available or has been deleted","anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"transcription_provider":{"description":"The transcription provider used (e.g., 'gladia'). Null if transcription was not enabled or if provider information is not available","anyOf":[{"type":"string"},{"type":"null"}]},"transcription_ids":{"description":"Array of transcription job IDs from the transcription provider. Null if transcription was not enabled or if IDs are not available","anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}]},"sent_at":{"description":"ISO 8601 timestamp when this webhook was sent","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["bot_id","event_id","participants","speakers","duration_seconds","joined_at","exited_at","data_deleted","video","audio","diarization","raw_transcription","transcription","transcription_provider","transcription_ids","sent_at"],"additionalProperties":false},"extra":{"description":"Additional metadata provided when creating the bot. This is user-defined data that can be used for correlation or tracking","anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]}},"required":["event","data","extra"],"additionalProperties":false},"BotWebhookFailed":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/CallbackFailed","type":"object","properties":{"event":{"description":"The webhook event type","type":"string","const":"bot.failed"},"data":{"type":"object","properties":{"bot_id":{"description":"The UUID of the bot that failed","type":"string","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)$"},"event_id":{"description":"The UUID of the calendar event associated with this bot. Null for non-calendar bots","anyOf":[{"type":"string","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":"null"}]},"error_message":{"description":"Human-readable error message describing why the bot failed","type":"string"},"error_code":{"description":"Machine-readable error code for programmatic handling. Common codes include 'MEETING_NOT_FOUND', 'MEETING_ENDED', 'BOT_CRASHED', etc.","type":"string"},"sent_at":{"description":"ISO 8601 timestamp when this webhook was sent","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["bot_id","event_id","error_message","error_code","sent_at"],"additionalProperties":false},"extra":{"description":"Additional metadata provided when creating the bot. This is user-defined data that can be used for correlation or tracking","anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]}},"required":["event","data","extra"],"additionalProperties":false},"BotWebhookChatMessage":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/BotWebhookChatMessage","type":"object","properties":{"event":{"description":"The webhook event type","type":"string","const":"bot.chat_message"},"data":{"type":"object","properties":{"bot_id":{"description":"The UUID of the bot that received the chat message","type":"string","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)$"},"event_id":{"description":"The UUID of the calendar event associated with this bot. Null for non-calendar bots","anyOf":[{"type":"string","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":"null"}]},"message_id":{"description":"Unique identifier of the chat message","type":"string"},"sender_name":{"description":"Display name of the message sender","type":"string"},"sender_id":{"description":"Sequential participant ID of the sender. Null if the sender could not be resolved to a participant","anyOf":[{"type":"integer","minimum":0,"maximum":9007199254740991},{"type":"null"}]},"text":{"description":"Text content of the chat message","type":"string"},"sent_at":{"description":"ISO 8601 timestamp when this webhook was sent","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["bot_id","event_id","message_id","sender_name","sender_id","text","sent_at"],"additionalProperties":false},"extra":{"description":"Additional metadata provided when creating the bot. This is user-defined data that can be used for correlation or tracking","anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]}},"required":["event","data","extra"],"additionalProperties":false},"CalendarWebhookConnectionCreated":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/CalendarWebhookConnectionCreated","type":"object","properties":{"event":{"description":"The webhook event type","type":"string","const":"calendar.connection_created"},"data":{"type":"object","properties":{"calendar_id":{"description":"The UUID of the newly created calendar connection","type":"string","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)$"},"calendar_platform":{"description":"The calendar platform. Either 'google' for Google Calendar or 'microsoft' for Microsoft Outlook/365","type":"string","enum":["google","microsoft"]},"account_email":{"description":"The email address associated with the calendar account","type":"string"},"status":{"description":"The current status of the calendar connection. Possible values: 'active' (connection is working), 'error' (connection has errors), 'revoked' (OAuth access was revoked), 'permission_denied' (insufficient permissions)","type":"string","enum":["active","error","revoked","permission_denied"]},"created_at":{"description":"ISO 8601 timestamp when the calendar connection was created","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["calendar_id","calendar_platform","account_email","status","created_at"],"additionalProperties":false}},"required":["event","data"],"additionalProperties":false},"CalendarWebhookConnectionUpdated":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/CalendarWebhookConnectionUpdated","type":"object","properties":{"event":{"description":"The webhook event type","type":"string","const":"calendar.connection_updated"},"data":{"type":"object","properties":{"calendar_id":{"description":"The UUID of the updated calendar connection","type":"string","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)$"},"calendar_platform":{"description":"The calendar platform. Either 'google' for Google Calendar or 'microsoft' for Microsoft Outlook/365","type":"string","enum":["google","microsoft"]},"account_email":{"description":"The email address associated with the calendar account","type":"string"},"status":{"description":"The current status of the calendar connection after the update. Possible values: 'active' (connection is working), 'error' (connection has errors), 'revoked' (OAuth access was revoked), 'permission_denied' (insufficient permissions)","type":"string","enum":["active","error","revoked","permission_denied"]},"created_at":{"description":"ISO 8601 timestamp when the calendar connection was originally created","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"updated_at":{"description":"ISO 8601 timestamp when the calendar connection was updated","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["calendar_id","calendar_platform","account_email","status","created_at","updated_at"],"additionalProperties":false}},"required":["event","data"],"additionalProperties":false},"CalendarWebhookConnectionDeleted":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/CalendarWebhookConnectionDeleted","type":"object","properties":{"event":{"description":"The webhook event type","type":"string","const":"calendar.connection_deleted"},"data":{"type":"object","properties":{"calendar_id":{"description":"The UUID of the deleted calendar connection","type":"string","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)$"},"calendar_platform":{"description":"The calendar platform. Either 'google' for Google Calendar or 'microsoft' for Microsoft Outlook/365","type":"string","enum":["google","microsoft"]},"deleted_at":{"description":"ISO 8601 timestamp when the calendar connection was deleted","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["calendar_id","calendar_platform","deleted_at"],"additionalProperties":false}},"required":["event","data"],"additionalProperties":false},"CalendarWebhookEventsSynced":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/CalendarWebhookEventsSynced","type":"object","properties":{"event":{"description":"The webhook event type","type":"string","const":"calendar.events_synced"},"data":{"type":"object","properties":{"calendar_id":{"description":"The UUID of the calendar connection that was synced","type":"string","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)$"},"events":{"description":"Array of event series that were synced. Each series contains its event instances","type":"array","items":{"type":"object","properties":{"event_type":{"description":"The type of event. 'one_off' for single events, 'recurring' for events that are part of a recurring series","type":"string","enum":["one_off","recurring"]},"series_id":{"description":"The UUID of the event series. Null only in rare cases where the series relationship could not be established","anyOf":[{"type":"string","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":"null"}]},"series_bot_scheduled":{"description":"Whether a bot has been scheduled for all occurrences of this series. True if a calendar bot schedule exists for the entire series","type":"boolean"},"instances":{"description":"Array of event instances that were synced. For one-off events, this contains a single instance. For recurring events, this contains all instances that were synced","type":"array","items":{"type":"object","properties":{"event_id":{"description":"The UUID of the event instance","type":"string","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)$"},"start":{"description":"ISO 8601 timestamp when the event starts","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"end":{"description":"ISO 8601 timestamp when the event ends","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"title":{"description":"The title of the event","type":"string"},"status":{"description":"The status of the event. Possible values: 'confirmed' (event is confirmed), 'cancelled' (event has been cancelled), 'tentative' (event is tentative)","type":"string","enum":["confirmed","cancelled","tentative"]},"is_all_day":{"description":"Whether this is an all-day event. True if the event spans entire days without specific start/end times","type":"boolean"},"is_exception":{"description":"Whether this is an exception to a recurring series. True if this instance has been modified differently from the recurring pattern","type":"boolean"},"bot_scheduled":{"description":"Whether a bot has been scheduled for this event instance. True if a calendar bot schedule exists for this event","type":"boolean"},"meeting_url":{"description":"The meeting URL extracted from the event. Null if the calendar platform did not include a meeting link in the event","anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"meeting_platform":{"description":"The meeting platform detected from the meeting URL. Null if no meeting link was found in the event. Possible values: 'zoom', 'meet', or 'teams'","anyOf":[{"type":"string","enum":["zoom","meet","teams"]},{"type":"null"}]}},"required":["event_id","start","end","title","status","is_all_day","is_exception","bot_scheduled","meeting_url","meeting_platform"],"additionalProperties":false}}},"required":["event_type","series_id","series_bot_scheduled","instances"],"additionalProperties":false}}},"required":["calendar_id","events"],"additionalProperties":false}},"required":["event","data"],"additionalProperties":false},"CalendarWebhookEventCreated":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/CalendarWebhookEventCreated","type":"object","properties":{"event":{"description":"The webhook event type","type":"string","const":"calendar.event_created"},"data":{"type":"object","properties":{"calendar_id":{"description":"The UUID of the calendar connection where the event was created","type":"string","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)$"},"event_type":{"description":"The type of event. 'one_off' for single events, 'recurring' for events that are part of a recurring series","type":"string","enum":["one_off","recurring"]},"series_id":{"description":"The UUID of the event series. Null only in rare cases where the series relationship could not be established","anyOf":[{"type":"string","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":"null"}]},"series_bot_scheduled":{"description":"Whether a bot has been scheduled for all occurrences of this series. True if a calendar bot schedule exists for the entire series","type":"boolean"},"instances":{"description":"Array of event instances that were created. For one-off events, this contains a single instance. For recurring events, this contains all instances that were created","type":"array","items":{"type":"object","properties":{"event_id":{"description":"The UUID of the event instance","type":"string","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)$"},"start":{"description":"ISO 8601 timestamp when the event starts","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"end":{"description":"ISO 8601 timestamp when the event ends","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"title":{"description":"The title of the event","type":"string"},"status":{"description":"The status of the event. Possible values: 'confirmed' (event is confirmed), 'cancelled' (event has been cancelled), 'tentative' (event is tentative)","type":"string","enum":["confirmed","cancelled","tentative"]},"is_all_day":{"description":"Whether this is an all-day event. True if the event spans entire days without specific start/end times","type":"boolean"},"is_exception":{"description":"Whether this is an exception to a recurring series. True if this instance has been modified differently from the recurring pattern","type":"boolean"},"bot_scheduled":{"description":"Whether a bot has been scheduled for this event instance. True if a calendar bot schedule exists for this event","type":"boolean"},"meeting_url":{"description":"The meeting URL extracted from the event. Null if the calendar platform did not include a meeting link in the event","anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"meeting_platform":{"description":"The meeting platform detected from the meeting URL. Null if no meeting link was found in the event. Possible values: 'zoom', 'meet', or 'teams'","anyOf":[{"type":"string","enum":["zoom","meet","teams"]},{"type":"null"}]}},"required":["event_id","start","end","title","status","is_all_day","is_exception","bot_scheduled","meeting_url","meeting_platform"],"additionalProperties":false}}},"required":["calendar_id","event_type","series_id","series_bot_scheduled","instances"],"additionalProperties":false}},"required":["event","data"],"additionalProperties":false},"CalendarWebhookEventUpdated":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/CalendarWebhookEventUpdated","type":"object","properties":{"event":{"description":"The webhook event type","type":"string","const":"calendar.event_updated"},"data":{"type":"object","properties":{"calendar_id":{"description":"The UUID of the calendar connection where the event was updated","type":"string","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)$"},"event_type":{"description":"The type of event. 'one_off' for single events, 'recurring' for events that are part of a recurring series","type":"string","enum":["one_off","recurring"]},"series_id":{"description":"The UUID of the event series. Null only in rare cases where the series relationship could not be established","anyOf":[{"type":"string","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":"null"}]},"series_bot_scheduled":{"description":"Whether a bot has been scheduled for all occurrences of this series. True if a calendar bot schedule exists for the entire series","type":"boolean"},"is_exception":{"description":"Whether the updated instance is an exception to a recurring series. True if this instance has been modified differently from the recurring pattern","type":"boolean"},"affected_instances":{"description":"Array of event instances that were affected by the update. This includes the instance that was directly updated and any related instances","type":"array","items":{"type":"object","properties":{"event_id":{"description":"The UUID of the event instance","type":"string","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)$"},"start":{"description":"ISO 8601 timestamp when the event starts","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"end":{"description":"ISO 8601 timestamp when the event ends","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"title":{"description":"The title of the event","type":"string"},"status":{"description":"The status of the event. Possible values: 'confirmed' (event is confirmed), 'cancelled' (event has been cancelled), 'tentative' (event is tentative)","type":"string","enum":["confirmed","cancelled","tentative"]},"is_all_day":{"description":"Whether this is an all-day event. True if the event spans entire days without specific start/end times","type":"boolean"},"is_exception":{"description":"Whether this is an exception to a recurring series. True if this instance has been modified differently from the recurring pattern","type":"boolean"},"bot_scheduled":{"description":"Whether a bot has been scheduled for this event instance. True if a calendar bot schedule exists for this event","type":"boolean"},"meeting_url":{"description":"The meeting URL extracted from the event. Null if the calendar platform did not include a meeting link in the event","anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"meeting_platform":{"description":"The meeting platform detected from the meeting URL. Null if no meeting link was found in the event. Possible values: 'zoom', 'meet', or 'teams'","anyOf":[{"type":"string","enum":["zoom","meet","teams"]},{"type":"null"}]}},"required":["event_id","start","end","title","status","is_all_day","is_exception","bot_scheduled","meeting_url","meeting_platform"],"additionalProperties":false}}},"required":["calendar_id","event_type","series_id","series_bot_scheduled","is_exception","affected_instances"],"additionalProperties":false}},"required":["event","data"],"additionalProperties":false},"CalendarWebhookEventCancelled":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/CalendarWebhookEventCancelled","type":"object","properties":{"event":{"description":"The webhook event type","type":"string","const":"calendar.event_cancelled"},"data":{"type":"object","properties":{"calendar_id":{"description":"The UUID of the calendar connection where the event was cancelled","type":"string","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)$"},"event_type":{"description":"The type of event. 'one_off' for single events, 'recurring' for events that are part of a recurring series","type":"string","enum":["one_off","recurring"]},"series_id":{"description":"The UUID of the event series. Null only in rare cases where the series relationship could not be established","anyOf":[{"type":"string","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":"null"}]},"cancelled_instances":{"description":"Array of event instances that were cancelled. For one-off events, this contains a single instance. For recurring events, this contains all instances that were cancelled","type":"array","items":{"type":"object","properties":{"event_id":{"description":"The UUID of the event instance","type":"string","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)$"},"start":{"description":"ISO 8601 timestamp when the event starts","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"end":{"description":"ISO 8601 timestamp when the event ends","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"title":{"description":"The title of the event","type":"string"},"status":{"description":"The status of the event. Possible values: 'confirmed' (event is confirmed), 'cancelled' (event has been cancelled), 'tentative' (event is tentative)","type":"string","enum":["confirmed","cancelled","tentative"]},"is_all_day":{"description":"Whether this is an all-day event. True if the event spans entire days without specific start/end times","type":"boolean"},"is_exception":{"description":"Whether this is an exception to a recurring series. True if this instance has been modified differently from the recurring pattern","type":"boolean"},"bot_scheduled":{"description":"Whether a bot has been scheduled for this event instance. True if a calendar bot schedule exists for this event","type":"boolean"},"meeting_url":{"description":"The meeting URL extracted from the event. Null if the calendar platform did not include a meeting link in the event","anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"meeting_platform":{"description":"The meeting platform detected from the meeting URL. Null if no meeting link was found in the event. Possible values: 'zoom', 'meet', or 'teams'","anyOf":[{"type":"string","enum":["zoom","meet","teams"]},{"type":"null"}]}},"required":["event_id","start","end","title","status","is_all_day","is_exception","bot_scheduled","meeting_url","meeting_platform"],"additionalProperties":false}}},"required":["calendar_id","event_type","series_id","cancelled_instances"],"additionalProperties":false}},"required":["event","data"],"additionalProperties":false},"CallbackCompleted":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/CallbackCompleted","type":"object","properties":{"event":{"description":"The webhook event type","type":"string","const":"bot.completed"},"data":{"type":"object","properties":{"bot_id":{"description":"The UUID of the bot that completed","type":"string","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)$"},"event_id":{"description":"The UUID of the calendar event associated with this bot. Null for non-calendar bots","anyOf":[{"type":"string","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":"null"}]},"participants":{"description":"List of participants who joined the meeting with their names and metadata. Empty array if participant information is not available","type":"array","items":{"type":"object","properties":{"name":{"description":"Participant's name (full name or display name)","type":"string"},"id":{"description":"Sequential participant ID (1, 2, 3...). Null if not available","anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"display_name":{"description":"Display name shown in UI (if different from name)","type":"string"},"profile_picture":{"description":"Profile picture URL (if available)","type":"string","format":"uri"}},"required":["name","id"],"additionalProperties":false}},"speakers":{"description":"List of speakers detected in the meeting with their names and metadata. Empty array if speaker information is not available","type":"array","items":{"type":"object","properties":{"name":{"description":"Participant's name (full name or display name)","type":"string"},"id":{"description":"Sequential participant ID (1, 2, 3...). Null if not available","anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"display_name":{"description":"Display name shown in UI (if different from name)","type":"string"},"profile_picture":{"description":"Profile picture URL (if available)","type":"string","format":"uri"}},"required":["name","id"],"additionalProperties":false}},"duration_seconds":{"anyOf":[{"description":"The duration of the meeting in seconds. Null if duration could not be determined","type":"integer","minimum":0,"maximum":9007199254740991},{"type":"null"}]},"joined_at":{"description":"ISO 8601 timestamp when the bot joined the meeting. Null if join time is not available","anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"exited_at":{"description":"ISO 8601 timestamp when the bot exited the meeting. Null if exit time is not available","anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"data_deleted":{"description":"Whether the bot's data (artifacts, recordings) has been deleted. True if data has been permanently removed","type":"boolean"},"video":{"description":"Signed URL to download the video recording. Valid for 4 hours. Null if video recording is not available or has been deleted","anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"audio":{"description":"Signed URL to download the audio recording. Valid for 4 hours. Null if audio recording is not available or has been deleted","anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"diarization":{"description":"Signed URL to download the speaker diarization data. Valid for 4 hours. Null if diarization is not available or has been deleted","anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"raw_transcription":{"description":"Signed URL to download the raw transcription file. Valid for 4 hours. Null if raw transcription is not available or has been deleted","anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"transcription":{"description":"Signed URL to download the processed transcription file. Valid for 4 hours. Null if transcription is not available or has been deleted","anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"transcription_provider":{"description":"The transcription provider used (e.g., 'gladia'). Null if transcription was not enabled or if provider information is not available","anyOf":[{"type":"string"},{"type":"null"}]},"transcription_ids":{"description":"Array of transcription job IDs from the transcription provider. Null if transcription was not enabled or if IDs are not available","anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}]},"sent_at":{"description":"ISO 8601 timestamp when this webhook was sent","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["bot_id","event_id","participants","speakers","duration_seconds","joined_at","exited_at","data_deleted","video","audio","diarization","raw_transcription","transcription","transcription_provider","transcription_ids","sent_at"],"additionalProperties":false},"extra":{"description":"Additional metadata provided when creating the bot. This is user-defined data that can be used for correlation or tracking","anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]}},"required":["event","data","extra"],"additionalProperties":false},"CallbackFailed":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/CallbackFailed","type":"object","properties":{"event":{"description":"The webhook event type","type":"string","const":"bot.failed"},"data":{"type":"object","properties":{"bot_id":{"description":"The UUID of the bot that failed","type":"string","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)$"},"event_id":{"description":"The UUID of the calendar event associated with this bot. Null for non-calendar bots","anyOf":[{"type":"string","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":"null"}]},"error_message":{"description":"Human-readable error message describing why the bot failed","type":"string"},"error_code":{"description":"Machine-readable error code for programmatic handling. Common codes include 'MEETING_NOT_FOUND', 'MEETING_ENDED', 'BOT_CRASHED', etc.","type":"string"},"sent_at":{"description":"ISO 8601 timestamp when this webhook was sent","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["bot_id","event_id","error_message","error_code","sent_at"],"additionalProperties":false},"extra":{"description":"Additional metadata provided when creating the bot. This is user-defined data that can be used for correlation or tracking","anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]}},"required":["event","data","extra"],"additionalProperties":false},"OutputTranscription":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/OutputTranscription","type":"object","properties":{"bot_id":{"description":"The bot UUID","type":"string","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)$"},"provider":{"description":"The transcription provider","type":"string","const":"gladia"},"result":{"type":"object","properties":{"utterances":{"description":"Array of diarized utterances, sorted chronologically","type":"array","items":{"type":"object","properties":{"text":{"description":"The transcribed text for this utterance","type":"string"},"language":{"description":"ISO 639-1 language code (e.g., 'en', 'es')","type":"string"},"start":{"description":"Start time in seconds (floating point)","type":"number"},"end":{"description":"End time in seconds (floating point)","type":"number"},"confidence":{"description":"Confidence score (0.0 to 1.0)","type":"number","minimum":0,"maximum":1},"channel":{"description":"Audio channel number","type":"number"},"words":{"description":"Array of word-level timestamps","type":"array","items":{"type":"object","properties":{"word":{"description":"The word text","type":"string"},"start":{"description":"Start time in seconds","type":"number"},"end":{"description":"End time in seconds","type":"number"},"confidence":{"description":"Confidence score (0.0 to 1.0)","type":"number","minimum":0,"maximum":1}},"required":["word","start","end","confidence"],"additionalProperties":false}},"speaker":{"description":"Real speaker name","type":"string"}},"required":["text","language","start","end","confidence","channel","words","speaker"],"additionalProperties":false}},"languages":{"description":"Array of detected language codes","type":"array","items":{"type":"string"}},"total_utterances":{"description":"Total number of utterances","type":"integer","minimum":0,"maximum":9007199254740991},"total_duration":{"description":"Total duration of the meeting in seconds","type":"number","minimum":0}},"required":["utterances","languages","total_utterances","total_duration"],"additionalProperties":false},"created_at":{"description":"ISO 8601 timestamp when the transcription was created","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["bot_id","provider","result","created_at"],"additionalProperties":false},"ZoomDiarizationSegment":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/ZoomDiarizationSegment","type":"object","properties":{"speaker":{"description":"Real speaker name","type":"string"},"start_time":{"description":"Start time in seconds","type":"number"},"end_time":{"description":"End time in seconds","type":"number"},"user_id":{"description":"Platform user ID (Zoom only)","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"lang":{"description":"Language code (optional)","type":"string"}},"required":["speaker","start_time","end_time","user_id"],"additionalProperties":false},"MeetTeamsDiarizationSegment":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/MeetTeamsDiarizationSegment","type":"object","properties":{"speaker":{"description":"Real speaker name","type":"string"},"start_time":{"description":"Start time in seconds","type":"number"},"end_time":{"description":"End time in seconds","type":"number"}},"required":["speaker","start_time","end_time"],"additionalProperties":false},"DiarizationSegment":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/DiarizationSegment","anyOf":[{"$ref":"#/components/schemas/ZoomDiarizationSegment"},{"$ref":"#/components/schemas/MeetTeamsDiarizationSegment"}]},"RawTranscription":{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"#/components/schemas/RawTranscription","type":"object","properties":{"bot_id":{"description":"The bot UUID","type":"string","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)$"},"transcriptions":{"description":"Array of transcription payloads, one per audio chunk","type":"array","items":{"description":"Gladia transcription payload with provider-specific features. Additional fields may be present based on custom parameters.","type":"object","properties":{"metadata":{"type":"object","properties":{"audio_duration":{"description":"Audio duration in seconds","type":"number"},"number_of_distinct_channels":{"description":"Number of distinct audio channels","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"billing_time":{"description":"Billing time in seconds","type":"number"},"transcription_time":{"description":"Transcription processing time in seconds","type":"number"}},"required":["audio_duration","number_of_distinct_channels","billing_time","transcription_time"],"additionalProperties":false},"transcription":{"type":"object","properties":{"full_transcript":{"description":"Full transcript text","type":"string"},"languages":{"description":"Array of detected language codes","type":"array","items":{"type":"string"}},"utterances":{"description":"Array of utterances","type":"array","items":{"type":"object","properties":{"text":{"type":"string"},"language":{"type":"string"},"start":{"type":"number"},"end":{"type":"number"},"confidence":{"type":"number","minimum":0,"maximum":1},"channel":{"type":"number"},"words":{"type":"array","items":{"type":"object","properties":{"word":{"type":"string"},"start":{"type":"number"},"end":{"type":"number"},"confidence":{"type":"number","minimum":0,"maximum":1}},"required":["word","start","end","confidence"],"additionalProperties":false}},"speaker":{"description":"Gladia's numeric speaker ID (0, 1, 2, etc.)","type":"number"}},"required":["text","language","start","end","confidence","channel","words","speaker"],"additionalProperties":false}},"error":{"description":"Error information if transcription failed"}},"required":["languages","utterances"],"additionalProperties":false},"summarization":{"description":"AI-generated meeting summary","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"translation":{"description":"Translated transcriptions by target language","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"sentiment_analysis":{"description":"Sentiment scores for utterances","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"named_entity_recognition":{"description":"Extracted entities (names, organizations, locations)","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"audio_to_llm":{"description":"LLM prompt responses","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"moderation":{"description":"Content moderation results","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"chapterization":{"description":"Automatic meeting chapters","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["metadata","transcription"],"additionalProperties":{}}},"created_at":{"description":"ISO 8601 timestamp when the combined transcription was created","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["bot_id","transcriptions","created_at"],"additionalProperties":false}}},"paths":{"/v2/bots":{"post":{"operationId":"createBot","summary":"Create a bot","tags":["Bots"],"description":"Create a bot to join a meeting immediately.\n    \n    The bot will automatically join the meeting, request recording permissions, and start recording once accepted. You can provide a bot-specific callback URL to receive bot.completed and bot.failed events for this bot (in addition to your account's webhooks). The bot will send webhook events for status changes, completion, and failures.\n    \n    Returns a `bot_id` (UUID) that you can use to track status, retrieve meeting data, and manage the bot. The bot will be queued immediately and join the meeting as soon as possible (may take up to 2 minutes depending on availability of bot slots).\n    \n    **Token Reservation:** 0.5 tokens are reserved immediately upon creation. These tokens will be consumed based on the bot's duration and outcome. If the bot fails due to user-responsible errors (`BOT_NOT_ACCEPTED`, `TIMEOUT_WAITING_TO_START`), recording tokens will be charged based on the time spent in the waiting room.\n    \n    **Deduplication:** By default, multiple bots can join the same meeting URL. Set `allow_multiple_bots: false` to prevent duplicate bots within 5 minutes. The deduplication check expires after 5 minutes, allowing a new bot to join the same meeting URL after that period.\n    \n    **Rate Limits:** Subject to your API key's rate limits and your team's daily bot cap. The daily bot cap is checked before token reservation. If the cap is reached, the request will fail with a 429 status code.\n    \n    **Error Scenarios:**\n    - `402 Payment Required`: Insufficient tokens available\n    - `409 Conflict`: Bot already exists for the same meeting URL (when `allow_multiple_bots` is false)\n    - `429 Too Many Requests`: Daily bot cap reached or rate limit exceeded","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateBotRequestBodyInput"}}}},"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateBotResponse"}}}},"400":{"description":"Bad Request - Invalid input or validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"402":{"description":"Payment Required - Insufficient tokens","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict - Bot already exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate Limited - Exceeded rate limit","content":{"application/json":{"schema":{"description":"Rate Limited - Exceeded rate limit","type":"object","properties":{"success":{"default":false,"type":"boolean","enum":[false]},"error":{"description":"Human-readable error message","type":"string"},"code":{"description":"Error code for programmatic handling","type":"string"},"statusCode":{"description":"HTTP status code","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"message":{"description":"Human-readable error message","anyOf":[{"type":"string"},{"type":"null"}]},"details":{"description":"Additional error details (string or null)","anyOf":[{"type":"string"},{"type":"null"}]},"retryAfter":{"description":"Number of seconds to wait before retrying","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["success","error","code","statusCode"],"additionalProperties":false}}}},"500":{"description":"Internal Server Error - Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"get":{"operationId":"listBots","summary":"List bots","tags":["Bots"],"description":"List all bots for your team with pagination support.\n    \n    Filter by status (queued, joining, in_call_recording, transcribing, completed, failed), meeting platform (zoom, meet, teams), and date range. Results are ordered by creation date (newest first). Use cursor-based pagination for efficient navigation through large result sets.\n    \n    **Pagination:** Uses cursor-based pagination. Provide a `cursor` query parameter to fetch the next page. The response includes a `next_cursor` if more results are available. The `limit` parameter controls how many results are returned per page (default: 50, max: 250).\n    \n    **Filtering:** \n    - `status`: Filter by bot status (comma-separated for multiple statuses)\n    - `platform`: Filter by meeting platform (zoom, meet, teams)\n    - `created_after`: ISO 8601 timestamp - only return bots created after this time\n    - `created_before`: ISO 8601 timestamp - only return bots created before this time\n    \n    **Date Range:** The `created_after` and `created_before` filters use ISO 8601 timestamps. Results are limited to bots created within the last 90 days by default.\n    \n    Returns a paginated list of bots with metadata including bot ID, status, meeting platform, creation time, and basic configuration.","parameters":[{"schema":{"example":null,"default":null,"anyOf":[{"type":"string"},{"type":"null"}]},"in":"query","name":"bot_name","required":false,"description":"Filter bots by name containing this string.\n\nPerforms a case-insensitive partial match on the bot's name. Useful for finding bots with specific naming conventions or to locate a particular bot when you don't have its ID.\n\nExample: \"Sales\" would match \"Sales Meeting\", \"Quarterly Sales\", etc."},{"schema":{"example":null,"default":null,"anyOf":[{"type":"string"},{"type":"null"}]},"in":"query","name":"bot_id","required":false,"description":"Filter bots by ID containing this string.\n\nPerforms a case-insensitive partial match on the bot's ID. Useful for finding bots with specific IDs or to locate a particular bot when you don't have its ID.\n\nExample: \"1234567890\" would match \"1234567890-1234-1234-1234-123456789012\""},{"schema":{"example":null,"default":null,"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"in":"query","name":"created_before","required":false,"description":"Filter bots created before this date.\n\nISO8601 format (e.g., \"2025-01-15T10:30:00Z\").\n\nCannot be more than 90 days before today and cannot be in the future.\n\nUse this in combination with `created_after` to filter bots within a specific date range.\n\nExample: \"2025-01-15T23:59:59Z\""},{"schema":{"example":null,"default":null,"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"in":"query","name":"created_after","required":false,"description":"Filter bots created after this date.\n\nISO8601 format (e.g., \"2025-01-01T00:00:00Z\").\n\nCannot be more than 90 days before today and cannot be in the future.\n\nUse this in combination with `created_before` to filter bots within a specific date range.\n\nExample: \"2025-01-01T00:00:00Z\""},{"schema":{"example":50,"default":50,"type":"integer","exclusiveMinimum":0,"maximum":250},"in":"query","name":"limit","required":true,"description":"Maximum number of bots to return in a single request.\n\nLimits the number of results returned in a single API call.\n\nDefault: 50 Minimum: 1 Maximum: 250"},{"schema":{"example":null,"default":null,"anyOf":[{"type":"string"},{"type":"null"}]},"in":"query","name":"cursor","required":false,"description":"The cursor to use for pagination.\n\nObtained from the `cursor` or `prev_cursor` field in the previous response.\n\nThe cursor is a base64-encoded string containing `<isoDate>::<id>`. To paginate backward, prefix the cursor with a `-` (minus sign).\n\nLeave as `null` to get the first page of results.\n\nExample: \"MjAyNS0wMS0xNVQxMDozMDowMFo6OjEyMzQ1\" or \"LU1qQXlOM1UxTmpVME5qVXhNakUwTkRrPQ==\" (for backward pagination)"},{"schema":{"example":null,"default":null,"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"in":"query","name":"ended_after","required":false,"description":"The date to filter bots ended after. ISO 8601 format."},{"schema":{"example":null,"default":null,"anyOf":[{"type":"string"},{"type":"null"}]},"in":"query","name":"extra","required":false,"description":"Filter bots by matching values in the extra JSON payload.\n\nThis parameter performs in-memory filtering on the `extra` JSON field, similar to a SQL WHERE clause. It reduces the result set to only include bots that match all specified conditions.\n\nFormat specifications: - Single condition: \"field:value\" - Multiple conditions: \"field1:value1,field2:value2\"\n\nExamples: - \"customer_id:12345\" - Only bots with this customer ID - \"status:active,project:sales\" - Only active bots from sales projects\n\nNotes: - All conditions must match for a bot to be included - Values are matched exactly (case-sensitive) - Bots without the specified field are excluded"},{"schema":{"example":null,"default":null,"anyOf":[{"type":"string"},{"type":"null"}]},"in":"query","name":"meeting_url","required":false,"description":"Filter bots by meeting URL containing this string.\n\nPerforms a case-insensitive partial match on the bot's meeting URL. Useful for finding bots associated with specific meeting platforms or particular meeting IDs.\n\nExample: \"zoom.us\" would match all Zoom meetings"},{"schema":{"example":null,"anyOf":[{"anyOf":[{"type":"string"},{"type":"null"}]},{"type":"null"}]},"in":"query","name":"meeting_platform","required":false,"description":"Filter bots by meeting platform.\n\nThis parameter filters bots by the platform they are associated with. It can be used to find bots that are associated with a specific meeting platform. Valid values are: \"zoom\", \"meet\", \"teams\".\n\nExample: \"zoom\" would match all bots associated with Zoom meetings.\n\nTo filter multiple platforms, use a comma-separated list of values. For example, \"zoom,meet\" would match all bots associated with Zoom or Meet meetings."},{"schema":{"example":null,"anyOf":[{"anyOf":[{"type":"string"},{"type":"null"}]},{"type":"null"}]},"in":"query","name":"status","required":false,"description":"Filter bots by bot statuses.\n\nThis parameter filters bots by their status. It can be used to find bots that have any of the specified statuses. Valid values are one or more of: queued, transcribing, completed, failed, joining_call, in_waiting_room, in_waiting_for_host, in_call_not_recording, in_call_recording, recording_paused, recording_resumed, call_ended, recording_succeeded, recording_failed, api_request_stop, bot_rejected, bot_removed, bot_removed_too_early, waiting_room_timeout, invalid_meeting_url, meeting_error.\n\nExample: \"queued,joining_call\" would match all bots that are queued or joining the call"}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListBotsResponse"}}}},"400":{"description":"Bad Request - Invalid input or validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"429":{"description":"Rate Limited - Exceeded rate limit","content":{"application/json":{"schema":{"description":"Rate Limited - Exceeded rate limit","type":"object","properties":{"success":{"default":false,"type":"boolean","enum":[false]},"error":{"description":"Human-readable error message","type":"string"},"code":{"description":"Error code for programmatic handling","type":"string"},"statusCode":{"description":"HTTP status code","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"message":{"description":"Human-readable error message","anyOf":[{"type":"string"},{"type":"null"}]},"details":{"description":"Additional error details (string or null)","anyOf":[{"type":"string"},{"type":"null"}]},"retryAfter":{"description":"Number of seconds to wait before retrying","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["success","error","code","statusCode"],"additionalProperties":false}}}},"500":{"description":"Internal Server Error - Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v2/bots/batch":{"post":{"operationId":"batchCreateBots","summary":"Create multiple bots","tags":["Bots"],"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.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchCreateBotsRequestBodyInput"}}}},"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchCreateBotResponse"}}}},"400":{"description":"Bad Request - Invalid input or validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"429":{"description":"Rate Limited - Exceeded rate limit","content":{"application/json":{"schema":{"description":"Rate Limited - Exceeded rate limit","type":"object","properties":{"success":{"default":false,"type":"boolean","enum":[false]},"error":{"description":"Human-readable error message","type":"string"},"code":{"description":"Error code for programmatic handling","type":"string"},"statusCode":{"description":"HTTP status code","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"message":{"description":"Human-readable error message","anyOf":[{"type":"string"},{"type":"null"}]},"details":{"description":"Additional error details (string or null)","anyOf":[{"type":"string"},{"type":"null"}]},"retryAfter":{"description":"Number of seconds to wait before retrying","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["success","error","code","statusCode"],"additionalProperties":false}}}},"500":{"description":"Internal Server Error - Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v2/bots/{bot_id}":{"get":{"operationId":"getBotDetails","summary":"Get bot details","tags":["Bots"],"description":"Get comprehensive information about a specific bot.\n    \n    Returns detailed bot information including current status, configuration, meeting metadata, and presigned URLs for all artifacts (video, audio, transcription, diarization). Artifact URLs are valid for 4 hours from the time of request. Returns `null` for artifacts if the bot's data has been deleted.\n    \n    **Artifact URLs:** All artifact URLs (video, audio, transcription, diarization) are presigned URLs that expire after 4 hours. If the bot's data has been deleted (via the delete-data endpoint or data retention policy), these fields will be `null`. The `artifacts_deleted` field indicates whether the bot's data has been permanently removed.\n    \n    **Status Information:** The response includes the bot's current status (`status` field) and timestamps for key events (joined_at, exited_at, created_at). If the bot failed, the response includes `error_code` and `error_message` fields with details about what went wrong.\n    \n    **Meeting Metadata:** Includes meeting platform, meeting URL, participants list, speakers list, and meeting duration (if available). Some metadata may be `null` if the bot failed before joining or if the information is not available.\n    \n    **Transcription Information:** If transcription was enabled, the response includes transcription provider, transcription IDs (for BYOK providers), and URLs to raw and processed transcription files.\n    \n    Returns 404 if the bot is not found or does not belong to your team.","parameters":[{"schema":{"type":"string","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)$"},"in":"path","name":"bot_id","required":true,"description":"The UUID of the bot to get details for."}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetBotDetailsResponse"}}}},"400":{"description":"Bad Request - Invalid input or validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"404":{"description":"Not Found - Bot not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate Limited - Exceeded rate limit","content":{"application/json":{"schema":{"description":"Rate Limited - Exceeded rate limit","type":"object","properties":{"success":{"default":false,"type":"boolean","enum":[false]},"error":{"description":"Human-readable error message","type":"string"},"code":{"description":"Error code for programmatic handling","type":"string"},"statusCode":{"description":"HTTP status code","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"message":{"description":"Human-readable error message","anyOf":[{"type":"string"},{"type":"null"}]},"details":{"description":"Additional error details (string or null)","anyOf":[{"type":"string"},{"type":"null"}]},"retryAfter":{"description":"Number of seconds to wait before retrying","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["success","error","code","statusCode"],"additionalProperties":false}}}},"500":{"description":"Internal Server Error - Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v2/bots/{bot_id}/status":{"get":{"operationId":"getBotStatus","summary":"Get bot status","tags":["Bots"],"description":"Get the current status of a bot, including the latest status code, transcription status, and timestamp.\n    \n    Useful for polling bot state without fetching the full bot details. Returns lightweight status information including the current status code, transcription status, and when the status was last updated (`updated_at`).\n    \n    **Response Fields:**\n    - `bot_id`: The UUID of the bot\n    - `status`: The current bot status (queued, joining, in_call_recording, transcribing, completed, failed)\n    - `transcription_status`: The current transcription status (not-applicable, not-started, queued, processing, done, error)\n    - `updated_at`: ISO 8601 timestamp when the status was last updated\n    \n    **Transcription Status:** The transcription status is fetched in real-time from the transcription provider (e.g., Gladia) if transcription is enabled. This allows you to track transcription progress separately from the bot's overall status.\n    \n    **Polling Considerations:** \n    - **Not Recommended for Active Monitoring:** Due to the nature of meetings running for extended periods (often hours), frequent polling is not recommended. Instead, use `callback_config` when creating bots or configure webhooks at the account level to receive real-time status updates.\n    - **Reconciliation Use Case:** This endpoint is better suited for reconciliation purposes (e.g., checking bot status after a webhook delivery failure or verifying final state).\n    - **If Polling is Necessary:** If you must poll, use a judicious interval (e.g., every 5-10 minutes) and implement exponential backoff to avoid rate limits. Consider the meeting duration when determining polling frequency.\n    \n    Returns 404 if the bot is not found or does not belong to your team.","parameters":[{"schema":{"type":"string","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)$"},"in":"path","name":"bot_id","required":true,"description":"The UUID of the bot to get status for."}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetBotStatusResponse"}}}},"400":{"description":"Bad Request - Invalid input or validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"404":{"description":"Not Found - Bot not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate Limited - Exceeded rate limit","content":{"application/json":{"schema":{"description":"Rate Limited - Exceeded rate limit","type":"object","properties":{"success":{"default":false,"type":"boolean","enum":[false]},"error":{"description":"Human-readable error message","type":"string"},"code":{"description":"Error code for programmatic handling","type":"string"},"statusCode":{"description":"HTTP status code","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"message":{"description":"Human-readable error message","anyOf":[{"type":"string"},{"type":"null"}]},"details":{"description":"Additional error details (string or null)","anyOf":[{"type":"string"},{"type":"null"}]},"retryAfter":{"description":"Number of seconds to wait before retrying","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["success","error","code","statusCode"],"additionalProperties":false}}}},"500":{"description":"Internal Server Error - Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v2/bots/{bot_id}/screenshots":{"get":{"operationId":"getBotScreenshots","summary":"Get bot screenshots","tags":["Bots"],"description":"Retrieve a paginated list of screenshot URLs captured during the meeting.\n    \n    Screenshots are taken periodically during the meeting and can be used to visualize meeting content. Each screenshot is a presigned URL valid for 4 hours.\n    \n    **Screenshot Availability:** \n    - Screenshots are only available for Google Meet and Microsoft Teams bots\n    - Screenshots are only available for bots with `recording_mode` set to `speaker_view` or `gallery_view`\n    - Audio-only recordings do not have screenshots\n    - Screenshots are captured at regular intervals during the meeting\n    \n    **Pagination:** Uses cursor-based pagination. Provide a `cursor` query parameter to fetch the next page. The `limit` parameter controls how many screenshots are returned per page (default: 50, max: 100).\n    \n    **URL Expiration:** All screenshot URLs are presigned URLs that expire after 4 hours. If the bot's data has been deleted, this endpoint will return an empty list.\n    \n    Returns 404 if the bot is not found or does not belong to your team.","parameters":[{"schema":{"default":50,"type":"integer","exclusiveMinimum":0,"maximum":250},"in":"query","name":"limit","required":true,"description":"Maximum number of screenshots to return (default: 50, max: 250)."},{"schema":{"example":null,"default":null,"anyOf":[{"type":"string"},{"type":"null"}]},"in":"query","name":"cursor","required":false,"description":"The cursor to use for pagination.\n\nObtained from the `cursor` or `prev_cursor` field in the previous response.\n\nThe cursor is a base64-encoded string containing the screenshot index. To paginate backward, prefix the cursor with a `-` (minus sign).\n\nLeave as `null` to get the first page of results.\n\nExample: \"MQ==\" (for index 1) or \"-MTA=\" (for backward pagination from index 10)"},{"schema":{"type":"string","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)$"},"in":"path","name":"bot_id","required":true,"description":"The UUID of the bot to get screenshots for."}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetBotScreenshotsResponse"}}}},"400":{"description":"Bad Request - Invalid input or validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"404":{"description":"Not Found - Bot not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate Limited - Exceeded rate limit","content":{"application/json":{"schema":{"description":"Rate Limited - Exceeded rate limit","type":"object","properties":{"success":{"default":false,"type":"boolean","enum":[false]},"error":{"description":"Human-readable error message","type":"string"},"code":{"description":"Error code for programmatic handling","type":"string"},"statusCode":{"description":"HTTP status code","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"message":{"description":"Human-readable error message","anyOf":[{"type":"string"},{"type":"null"}]},"details":{"description":"Additional error details (string or null)","anyOf":[{"type":"string"},{"type":"null"}]},"retryAfter":{"description":"Number of seconds to wait before retrying","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["success","error","code","statusCode"],"additionalProperties":false}}}},"500":{"description":"Internal Server Error - Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v2/bots/{bot_id}/leave":{"post":{"operationId":"leaveBot","summary":"Leave meeting","tags":["Bots"],"description":"Instruct a bot to leave the meeting immediately.\n    \n    The bot will stop recording and processing, then exit the meeting. Only works if the bot is currently in the meeting (status is `joining_call`, `in_waiting_room`, `in_call_not_recording`, `in_call_recording`, `recording_paused`, or `recording_resumed`). The bot will send a final webhook event when it leaves.\n    \n    **Status Requirements:** The bot must be in a state that allows leaving. Bots that have already completed, failed, or are not yet in the meeting cannot be left via this endpoint. If the bot is in an invalid state, the request will fail with a 409 Conflict status.\n    \n    **Token Consumption:** When a bot is manually left, tokens are consumed based on the duration from when recording started to when the bot left. The bot will transition to `completed` status and send a completion webhook.\n    \n    **Immediate Effect:** The leave command is sent to the bot process immediately. The bot will stop recording and exit the meeting as soon as it receives the command (usually within a few seconds).\n    \n    Returns 404 if the bot is not found, or 409 if the bot's status does not allow this operation.","parameters":[{"schema":{"type":"string","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)$"},"in":"path","name":"bot_id","required":true,"description":"The UUID of the bot to leave the meeting."}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeaveBotResponse"}}}},"400":{"description":"Bad Request - Invalid input or validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"404":{"description":"Not Found - Bot not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict - Bot status does not allow this operation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate Limited - Exceeded rate limit","content":{"application/json":{"schema":{"description":"Rate Limited - Exceeded rate limit","type":"object","properties":{"success":{"default":false,"type":"boolean","enum":[false]},"error":{"description":"Human-readable error message","type":"string"},"code":{"description":"Error code for programmatic handling","type":"string"},"statusCode":{"description":"HTTP status code","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"message":{"description":"Human-readable error message","anyOf":[{"type":"string"},{"type":"null"}]},"details":{"description":"Additional error details (string or null)","anyOf":[{"type":"string"},{"type":"null"}]},"retryAfter":{"description":"Number of seconds to wait before retrying","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["success","error","code","statusCode"],"additionalProperties":false}}}},"500":{"description":"Internal Server Error - Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v2/bots/{bot_id}/send-chat-message":{"post":{"operationId":"sendChatMessage","summary":"Send chat message","tags":["Bots"],"description":"Send a chat message to the meeting through the bot.\n\n    The message will be sent as the bot in the meeting's chat. The bot must be actively in the meeting to send messages. Messages are limited to 500 characters and cannot be empty or whitespace-only.\n\n    **Status Requirements:** The bot must be in one of the following statuses: `in_call_not_recording`, `in_call_recording`, `recording_paused`, or `recording_resumed`. If the bot is in any other state (e.g., `queued`, `joining_call`, `in_waiting_room`, `completed`, `failed`), the request will fail with a 409 Conflict error (`FST_ERR_BOT_STATUS`).\n\n    **Chat Disabled:** Some meetings have chat disabled by the host or meeting policy. If the bot attempts to send a message in a meeting where chat is not available, the request will fail with a 422 Unprocessable Entity error (`FST_ERR_CHAT_DISABLED`). This is determined at runtime by the meeting platform and cannot be known in advance. Chat disabled detection works for Zoom and Microsoft Teams meetings. For Google Meet, message delivery is best-effort — the bot may report success even if the host has restricted chat permissions for external participants.\n\n    **Message Delivery:** The message is forwarded to the bot process which sends it through the meeting platform's chat API (Google Meet, Microsoft Teams, or Zoom). Delivery is best-effort — if the bot process is unreachable or the platform rejects the message, the request will fail with a 500 Internal Server Error (`FST_ERR_SEND_CHAT_MESSAGE_FAILED`).\n\n    **Message Persistence:** Successfully sent messages are included in the `chat_messages` artifact alongside received messages when the bot completes. Bot-sent messages have `sender_id: null` and the bot's display name as `sender_name`.\n\n    Returns 404 if the bot is not found, 409 if the bot's status does not allow this operation, or 422 if chat is disabled in the meeting.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"description":"The chat message text to send in the meeting.","type":"string","minLength":1,"maxLength":500}},"required":["message"]}}},"required":true},"parameters":[{"schema":{"type":"string","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)$"},"in":"path","name":"bot_id","required":true,"description":"The UUID of the bot to send the chat message through."}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"message":{"description":"Success message","type":"string"}},"required":["message"],"additionalProperties":false}},"required":["success","data"],"additionalProperties":false}}}},"400":{"description":"Bad Request - Invalid input or validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"404":{"description":"Not Found - Bot not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict - Bot status does not allow this operation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable Entity - Chat is disabled in this meeting","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate Limited - Exceeded rate limit","content":{"application/json":{"schema":{"description":"Rate Limited - Exceeded rate limit","type":"object","properties":{"success":{"default":false,"type":"boolean","enum":[false]},"error":{"description":"Human-readable error message","type":"string"},"code":{"description":"Error code for programmatic handling","type":"string"},"statusCode":{"description":"HTTP status code","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"message":{"description":"Human-readable error message","anyOf":[{"type":"string"},{"type":"null"}]},"details":{"description":"Additional error details (string or null)","anyOf":[{"type":"string"},{"type":"null"}]},"retryAfter":{"description":"Number of seconds to wait before retrying","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["success","error","code","statusCode"],"additionalProperties":false}}}},"500":{"description":"Internal Server Error - Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v2/bots/{bot_id}/delete-data":{"delete":{"operationId":"deleteBotData","summary":"Delete bot data","tags":["Bots"],"description":"Permanently delete all bot data including recordings, transcripts, summaries, and screenshots.\n    \n    This operation is irreversible. All artifacts (video, audio, transcription, diarization, screenshots) will be permanently deleted. Optionally delete transcription data from the transcription provider as well using the `delete_transcription` query parameter.\n    \n    **Data Deletion:** \n    - All artifacts (video, audio, transcription, diarization, screenshots) are permanently deleted\n    - The `artifacts_deleted` field is set to `true`\n    - Artifact URLs will return `null` in subsequent API calls\n    - Bot metadata remains accessible but all associated data is removed\n    \n    **Transcription Provider Deletion:** If `delete_transcription=true` is provided, the transcription data will also be deleted from the transcription provider (e.g., Gladia). This requires the bot to have transcription enabled and a transcription provider configured. If the bot uses BYOK transcription, you must have access to the transcription provider API key.\n    \n    **Irreversible Operation:** Once data is deleted, it cannot be recovered. Make sure you have downloaded or backed up any data you need before calling this endpoint.\n    \n    **Status Requirements:** The bot must be in `completed` or `failed` status. Bots that are still in progress (queued, joining, in_call_recording, transcribing) cannot have their data deleted. If the bot is in an invalid state, the request will fail with a 409 Conflict status.\n    \n    Returns 404 if the bot is not found, or 409 if the bot's status does not allow this operation.","parameters":[{"schema":{"default":true,"type":"boolean"},"in":"query","name":"delete_from_provider","required":true,"description":"Whether to delete transcription data from the transcription provider.\n\nIf `true` (default), the transcription data will be deleted from the transcription provider's servers in addition to deleting artifacts from S3. This ensures complete data deletion.\n\nIf `false`, only S3 artifacts will be deleted, and transcription data will remain on the transcription provider's servers.\n\nNote: If the bot was created with a BYOK (Bring Your Own Key) transcription API key, the deletion will use that key to authenticate with the transcription provider.\n\nDefault: `true`"},{"schema":{"type":"string","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)$"},"in":"path","name":"bot_id","required":true,"description":"The UUID of the bot whose data should be deleted."}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteBotDataResponse"}}}},"400":{"description":"Bad Request - Invalid input or validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"404":{"description":"Not Found - Bot not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate Limited - Exceeded rate limit","content":{"application/json":{"schema":{"description":"Rate Limited - Exceeded rate limit","type":"object","properties":{"success":{"default":false,"type":"boolean","enum":[false]},"error":{"description":"Human-readable error message","type":"string"},"code":{"description":"Error code for programmatic handling","type":"string"},"statusCode":{"description":"HTTP status code","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"message":{"description":"Human-readable error message","anyOf":[{"type":"string"},{"type":"null"}]},"details":{"description":"Additional error details (string or null)","anyOf":[{"type":"string"},{"type":"null"}]},"retryAfter":{"description":"Number of seconds to wait before retrying","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["success","error","code","statusCode"],"additionalProperties":false}}}},"500":{"description":"Internal Server Error - Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v2/bots/{bot_id}/resend-webhook":{"post":{"operationId":"resendFinalWebhook","summary":"Resend final webhook","tags":["Bots"],"description":"Resend the final webhook (completed or failed) for a bot.\n    \n    Useful if the webhook delivery failed or you need to reprocess the webhook event. The webhook will be sent to all configured webhook endpoints for your account.\n    \n    **Webhook Delivery:** The webhook will be sent to all configured webhook endpoints for your account. The webhook payload will be identical to the original final webhook (either `bot.completed` or `bot.failed` event).\n    \n    **Status Requirements:** The bot must be in `completed` or `failed` status. Bots that are still in progress cannot have their final webhook resent. If the bot is in an invalid state, the request will fail with a 409 Conflict status.\n    \n    **Use Cases:** \n    - Webhook delivery failed due to network issues\n    - Webhook endpoint was temporarily unavailable\n    - Need to reprocess a webhook event\n    - Testing webhook integration\n    \n    **Idempotency:** This operation is idempotent. You can call it multiple times, and it will resend the webhook each time. There is no limit on how many times you can resend a webhook.\n    \n    Returns 404 if the bot is not found, or 409 if the bot's status does not allow this operation.","parameters":[{"schema":{"type":"string","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)$"},"in":"path","name":"bot_id","required":true,"description":"The UUID of the bot to resend the final webhook for.\n\nThis will recreate and resend the `bot.completed` or `bot.failed` webhook to all configured webhook endpoints."}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResendFinalWebhookResponse"}}}},"400":{"description":"Bad Request - Invalid input or validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"404":{"description":"Not Found - Bot not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict - Bot status does not allow this operation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate Limited - Exceeded rate limit","content":{"application/json":{"schema":{"description":"Rate Limited - Exceeded rate limit","type":"object","properties":{"success":{"default":false,"type":"boolean","enum":[false]},"error":{"description":"Human-readable error message","type":"string"},"code":{"description":"Error code for programmatic handling","type":"string"},"statusCode":{"description":"HTTP status code","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"message":{"description":"Human-readable error message","anyOf":[{"type":"string"},{"type":"null"}]},"details":{"description":"Additional error details (string or null)","anyOf":[{"type":"string"},{"type":"null"}]},"retryAfter":{"description":"Number of seconds to wait before retrying","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["success","error","code","statusCode"],"additionalProperties":false}}}},"500":{"description":"Internal Server Error - Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v2/bots/{bot_id}/retry-callback":{"post":{"operationId":"retryCallback","summary":"Retry callback","tags":["Bots"],"description":"Retry sending the transcription callback for a bot.\n    \n    You can override the callback configuration (URL, method, secret) if needed. Only works for bots that have completed or failed. The callback will be sent to the provided URL (or the bot's original callback URL if not overridden).\n    \n    **Callback Configuration:** You can override the callback URL, HTTP method (POST or PUT), and secret in the request body. If not provided, the bot's original callback configuration will be used. The secret will be included in the `x-mb-secret` header for validation.\n    \n    **Status Requirements:** The bot must be in `completed` or `failed` status and must have had transcription enabled. Bots without transcription or bots that are still in progress cannot have their callback retried. If the bot is in an invalid state, the request will fail with a 409 Conflict status.\n    \n    **Callback Payload:** The callback payload will be identical to the original callback (either `bot.completed` or `bot.failed` event with transcription data). The payload format matches the webhook format.\n    \n    **Use Cases:**\n    - Callback delivery failed due to network issues\n    - Callback endpoint was temporarily unavailable\n    - Need to send callback to a different endpoint\n    - Testing callback integration\n    \n    **Idempotency:** This operation is idempotent. You can call it multiple times with the same or different configurations.\n    \n    Returns 404 if the bot is not found, or 409 if the bot's status does not allow this operation or if no callback was configured.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RetryCallbackRequestBodyInput"}}}},"parameters":[{"schema":{"type":"string","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)$"},"in":"path","name":"bot_id","required":true,"description":"The UUID of the bot to retry the callback for.\n\nThis will recreate and resend the callback payload to the configured callback URL (or a custom URL if provided in the request body)."}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RetryCallbackResponse"}}}},"400":{"description":"Bad Request - Invalid input or validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"404":{"description":"Not Found - Bot not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict - Bot status does not allow this operation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate Limited - Exceeded rate limit","content":{"application/json":{"schema":{"description":"Rate Limited - Exceeded rate limit","type":"object","properties":{"success":{"default":false,"type":"boolean","enum":[false]},"error":{"description":"Human-readable error message","type":"string"},"code":{"description":"Error code for programmatic handling","type":"string"},"statusCode":{"description":"HTTP status code","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"message":{"description":"Human-readable error message","anyOf":[{"type":"string"},{"type":"null"}]},"details":{"description":"Additional error details (string or null)","anyOf":[{"type":"string"},{"type":"null"}]},"retryAfter":{"description":"Number of seconds to wait before retrying","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["success","error","code","statusCode"],"additionalProperties":false}}}},"500":{"description":"Internal Server Error - Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v2/bots/{bot_id}/update-config":{"patch":{"operationId":"updateBotConfig","summary":"Update bot configuration","tags":["Bots"],"description":"Update bot configuration (currently only supports updating the extra parameter).\n    \n    Allows updating the `extra` metadata even while the bot is running. The updated extra will be reflected in subsequent webhooks and API responses. This is useful when your system evolves and you need to attach additional tracking information to a bot after it has started.\n    \n    **Merge Behavior:** The `extra` parameter performs a shallow merge with the existing extra object:\n    - New keys are added to the existing extra object\n    - Existing keys are overwritten with new values\n    - Keys not included in the update request remain unchanged\n    - Pass `null` to clear all extra data\n    \n    **Example Merge:**\n    - Current extra: `{ \"customer_id\": \"123\", \"session_id\": \"abc\" }`\n    - Update with: `{ \"session_id\": \"xyz\", \"order_id\": \"456\" }`\n    - Result: `{ \"customer_id\": \"123\", \"session_id\": \"xyz\", \"order_id\": \"456\" }`\n    \n    **Webhook Behavior:** After updating extra, all future webhooks (including status updates) will use the new value from the database. The updated extra is fetched in real-time for each webhook, ensuring consistency.\n    \n    **Works for Any Bot Status:** You can update extra for bots in any status (queued, recording, completed, failed). This allows you to add correlation metadata even after a bot has finished.\n    \n    **Use Cases:**\n    - Add tracking IDs after bot creation\n    - Update correlation metadata when your system state changes\n    - Fix incorrect tracking information\n    - Add additional context for completed bots\n    \n    Returns 404 if the bot is not found or does not belong to your team.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"extra":{"description":"Custom metadata to merge with existing extra data (shallow merge)","example":{"foo":"bar"},"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]}},"required":["extra"]}}},"required":true},"parameters":[{"schema":{"type":"string","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)$"},"in":"path","name":"bot_id","required":true,"description":"The UUID of the bot to update configuration for."}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"message":{"description":"Success message","type":"string"}},"required":["message"],"additionalProperties":false}},"required":["success","data"],"additionalProperties":false}}}},"400":{"description":"Bad Request - Invalid input or validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"404":{"description":"Not Found - Bot not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate Limited - Exceeded rate limit","content":{"application/json":{"schema":{"description":"Rate Limited - Exceeded rate limit","type":"object","properties":{"success":{"default":false,"type":"boolean","enum":[false]},"error":{"description":"Human-readable error message","type":"string"},"code":{"description":"Error code for programmatic handling","type":"string"},"statusCode":{"description":"HTTP status code","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"message":{"description":"Human-readable error message","anyOf":[{"type":"string"},{"type":"null"}]},"details":{"description":"Additional error details (string or null)","anyOf":[{"type":"string"},{"type":"null"}]},"retryAfter":{"description":"Number of seconds to wait before retrying","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["success","error","code","statusCode"],"additionalProperties":false}}}},"500":{"description":"Internal Server Error - Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v2/bots/scheduled":{"post":{"operationId":"createScheduledBot","summary":"Create scheduled bot","tags":["Bots"],"description":"Schedule a bot to join a meeting at a specific time in the future.\n    \n    The bot will automatically join the meeting at the specified `join_at` time (ISO 8601 timestamp). You can provide a callback URL to receive events for this bot. The bot configuration is stored immediately, but token reservation and daily bot cap checks are performed when the bot actually joins the meeting.\n    \n    **Scheduling:** The `join_at` timestamp must be in the future (at least 1 minute ahead). The bot will automatically attempt to join the meeting at the specified time. There may be a small processing delay (typically less than a minute).\n    \n    **Token Reservation:** Tokens are NOT reserved at creation time. Token availability and daily bot cap are checked when the bot actually joins the meeting. If tokens are insufficient or the daily cap is reached at join time, the bot will fail with an appropriate error and transition to `failed` status.\n    \n    **Deduplication:** Deduplication is checked when the bot joins, not at creation time. This means you can schedule multiple bots for the same meeting URL, but only one will successfully join (unless `allow_multiple_bots` is true).\n    \n    **Status:** The scheduled bot starts in `scheduled` status and transitions to `completed` when the bot instance is created and queued to join. If the bot fails to join, it transitions to `failed` status.\n    \n    **Updates and Deletions:** Scheduled bots can be updated or deleted as long as they are in `scheduled` status and the join time is at least 4 minutes in the future. This ensures the bot can be modified before it starts processing.\n    \n    Returns a `bot_id` (UUID) that you can use to track and manage the scheduled bot. This UUID will be reused as the bot's UUID when it actually joins.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateScheduledBotRequestBodyInput"}}}},"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateScheduledBotResponse"}}}},"400":{"description":"Bad Request - Invalid input or validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"429":{"description":"Rate Limited - Exceeded rate limit","content":{"application/json":{"schema":{"description":"Rate Limited - Exceeded rate limit","type":"object","properties":{"success":{"default":false,"type":"boolean","enum":[false]},"error":{"description":"Human-readable error message","type":"string"},"code":{"description":"Error code for programmatic handling","type":"string"},"statusCode":{"description":"HTTP status code","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"message":{"description":"Human-readable error message","anyOf":[{"type":"string"},{"type":"null"}]},"details":{"description":"Additional error details (string or null)","anyOf":[{"type":"string"},{"type":"null"}]},"retryAfter":{"description":"Number of seconds to wait before retrying","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["success","error","code","statusCode"],"additionalProperties":false}}}},"500":{"description":"Internal Server Error - Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"get":{"operationId":"listScheduledBots","summary":"List scheduled bots","tags":["Bots"],"description":"Retrieve a paginated list of scheduled bots.\n    \n    Supports filtering by status (`scheduled`, `completed`, `failed`) and date range. Results are ordered by scheduled join time (earliest first). Use cursor-based pagination for efficient navigation.\n    \n    **Pagination:** Uses cursor-based pagination. Provide a `cursor` query parameter to fetch the next page. The `limit` parameter controls how many results are returned per page (default: 20, max: 100).\n    \n    **Filtering:**\n    - `status`: Filter by scheduled bot status (comma-separated for multiple statuses)\n    - `scheduled_after`: ISO 8601 timestamp - only return bots scheduled to join after this time\n    - `scheduled_before`: ISO 8601 timestamp - only return bots scheduled to join before this time\n    \n    **Status Values:**\n    - `scheduled`: Bot is scheduled but has not yet joined\n    - `completed`: Bot instance was created and queued to join (bot may still be joining)\n    - `failed`: Bot failed to join (token issues, daily cap, etc.)\n    \n    Returns a paginated list of scheduled bots with metadata including bot ID, scheduled join time, status, and basic configuration.","parameters":[{"schema":{"default":50,"type":"integer","exclusiveMinimum":0,"maximum":100},"in":"query","name":"limit","required":true,"description":"Maximum number of scheduled bots to return in a single request.\n\nLimits the number of results returned in a single API call.\n\nDefault: 50 Minimum: 1 Maximum: 100"},{"schema":{"example":null,"default":null,"anyOf":[{"type":"string"},{"type":"null"}]},"in":"query","name":"cursor","required":false,"description":"The cursor to use for pagination.\n\nObtained from the `cursor` or `prev_cursor` field in the previous response.\n\nThe cursor is a base64-encoded string containing `<isoDate>::<id>`. To paginate backward, prefix the cursor with a `-` (minus sign).\n\nLeave as `null` to get the first page of results.\n\nExample: \"MjAyNS0wMS0xNVQxMDozMDowMFo6OjEyMzQ1\" or \"LU1qQXlOM1UxTmpVME5qVXhNakUwTkRrPQ==\" (for backward pagination)"},{"schema":{"example":null,"default":null,"anyOf":[{"type":"string"},{"type":"null"}]},"in":"query","name":"bot_id","required":false,"description":"Filter scheduled bots by UUID (partial match, case-insensitive).\n\nUse this to find a scheduled bot when you only know part of the identifier."},{"schema":{"example":null,"default":null,"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"in":"query","name":"scheduled_before","required":false,"description":"Filter scheduled bots with join_at before this timestamp.\n\nReturns only scheduled bots that are scheduled to join before the specified date.\n\nISO 8601 format. Must be within ±90 days from today.\n\nExample: \"2025-12-25T10:00:00Z\""},{"schema":{"example":null,"default":null,"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"in":"query","name":"scheduled_after","required":false,"description":"Filter scheduled bots with join_at after this timestamp.\n\nReturns only scheduled bots that are scheduled to join after the specified date.\n\nISO 8601 format. Must be within ±90 days from today.\n\nExample: \"2025-12-25T10:00:00Z\""},{"schema":{"example":null,"anyOf":[{"anyOf":[{"type":"string"},{"type":"null"}]},{"type":"null"}]},"in":"query","name":"status","required":false,"description":"Filter by scheduled bot status.\n\nReturns only scheduled bots with the specified status(es).\n\nAvailable statuses:\n- scheduled: Bot is scheduled to join at a future time\n- cancelled: Bot schedule was cancelled\n- completed: Bot has completed its scheduled task\n- failed: Bot failed to execute its scheduled task\n\nTo filter multiple statuses, use a comma-separated list of values. For example, \"scheduled,completed\" would match all bots that are scheduled or completed."},{"schema":{"example":null,"default":null,"anyOf":[{"type":"string"},{"type":"null"}]},"in":"query","name":"bot_name","required":false,"description":"Filter bots by name containing this string.\n\nPerforms a case-insensitive partial match on the bot's name. Useful for finding bots with specific naming conventions or to locate a particular bot when you don't have its ID.\n\nExample: \"Sales\" would match \"Sales Meeting\", \"Quarterly Sales\", etc."},{"schema":{"example":null,"default":null,"anyOf":[{"type":"string"},{"type":"null"}]},"in":"query","name":"meeting_url","required":false,"description":"Filter bots by meeting URL containing this string.\n\nPerforms a case-insensitive partial match on the bot's meeting URL. Useful for finding bots associated with specific meeting platforms or particular meeting IDs.\n\nExample: \"zoom.us\" would match all Zoom meetings"},{"schema":{"example":null,"anyOf":[{"anyOf":[{"type":"string"},{"type":"null"}]},{"type":"null"}]},"in":"query","name":"meeting_platform","required":false,"description":"Filter by meeting platform.\n\nThis parameter filters scheduled bots by the platform they are associated with. It can be used to find bots that are associated with a specific meeting platform. Valid values are: \"zoom\", \"meet\", \"teams\".\n\nExample: \"zoom\" would match all bots associated with Zoom meetings.\n\nTo filter multiple platforms, use a comma-separated list of values. For example, \"zoom,meet\" would match all bots associated with Zoom or Meet meetings."}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListScheduledBotsResponse"}}}},"400":{"description":"Bad Request - Invalid input or validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"429":{"description":"Rate Limited - Exceeded rate limit","content":{"application/json":{"schema":{"description":"Rate Limited - Exceeded rate limit","type":"object","properties":{"success":{"default":false,"type":"boolean","enum":[false]},"error":{"description":"Human-readable error message","type":"string"},"code":{"description":"Error code for programmatic handling","type":"string"},"statusCode":{"description":"HTTP status code","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"message":{"description":"Human-readable error message","anyOf":[{"type":"string"},{"type":"null"}]},"details":{"description":"Additional error details (string or null)","anyOf":[{"type":"string"},{"type":"null"}]},"retryAfter":{"description":"Number of seconds to wait before retrying","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["success","error","code","statusCode"],"additionalProperties":false}}}},"500":{"description":"Internal Server Error - Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v2/bots/scheduled/batch":{"post":{"operationId":"batchCreateScheduledBots","summary":"Create multiple scheduled bots","tags":["Bots"],"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.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchCreateScheduledBotsRequestBodyInput"}}}},"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchCreateScheduledBotResponse"}}}},"400":{"description":"Bad Request - Invalid input or validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"429":{"description":"Rate Limited - Exceeded rate limit","content":{"application/json":{"schema":{"description":"Rate Limited - Exceeded rate limit","type":"object","properties":{"success":{"default":false,"type":"boolean","enum":[false]},"error":{"description":"Human-readable error message","type":"string"},"code":{"description":"Error code for programmatic handling","type":"string"},"statusCode":{"description":"HTTP status code","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"message":{"description":"Human-readable error message","anyOf":[{"type":"string"},{"type":"null"}]},"details":{"description":"Additional error details (string or null)","anyOf":[{"type":"string"},{"type":"null"}]},"retryAfter":{"description":"Number of seconds to wait before retrying","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["success","error","code","statusCode"],"additionalProperties":false}}}},"500":{"description":"Internal Server Error - Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v2/bots/scheduled/{bot_id}":{"get":{"operationId":"getScheduledBotDetails","summary":"Get scheduled bot details","tags":["Bots"],"description":"Retrieve detailed information about a specific scheduled bot.\n    \n    Returns the scheduled bot's configuration, scheduled join time, current status, and associated bot instance (if the bot has already joined). Includes all the same configuration options as immediate bot creation.\n    \n    **Status Information:** The response includes the scheduled bot's current status (`scheduled`, `completed`, or `failed`) and when the status was last updated. If the bot has joined, the response includes a link to the actual bot instance.\n    \n    **Scheduled Join Time:** The `join_at` field contains the ISO 8601 timestamp when the bot is scheduled to join the meeting.\n    \n    **Bot Instance:** If the scheduled bot has transitioned to `completed` status, the bot instance has been created and is queued to join. You can use the `bot_id` (which will be reused as the bot's UUID when it joins) to query the bot's status and retrieve meeting data once it has joined.\n    \n    **Updates and Deletions:** If the bot is in `scheduled` status and the join time is at least 4 minutes in the future, you can update or delete the scheduled bot. This ensures the bot can be modified before it starts processing.\n    \n    Returns 404 if the scheduled bot is not found or does not belong to your team.","parameters":[{"schema":{"type":"string","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)$"},"in":"path","name":"bot_id","required":true,"description":"The UUID of the scheduled bot to get details for."}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetScheduledBotResponse"}}}},"400":{"description":"Bad Request - Invalid input or validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"404":{"description":"Not Found - Scheduled bot not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate Limited - Exceeded rate limit","content":{"application/json":{"schema":{"description":"Rate Limited - Exceeded rate limit","type":"object","properties":{"success":{"default":false,"type":"boolean","enum":[false]},"error":{"description":"Human-readable error message","type":"string"},"code":{"description":"Error code for programmatic handling","type":"string"},"statusCode":{"description":"HTTP status code","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"message":{"description":"Human-readable error message","anyOf":[{"type":"string"},{"type":"null"}]},"details":{"description":"Additional error details (string or null)","anyOf":[{"type":"string"},{"type":"null"}]},"retryAfter":{"description":"Number of seconds to wait before retrying","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["success","error","code","statusCode"],"additionalProperties":false}}}},"500":{"description":"Internal Server Error - Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"updateScheduledBot","summary":"Update scheduled bot","tags":["Bots"],"description":"Update a scheduled bot's configuration or scheduled join time.\n    \n    The bot must be in `scheduled` status and the join time must be at least 4 minutes in the future. This ensures the bot can be updated before it starts processing.\n    \n    **Updateable Fields:** You can update any configuration field (bot name, image, recording mode, transcription settings, etc.) and the scheduled join time (`join_at`). All fields are optional - only provided fields will be updated.\n    \n    **Join Time Requirements:** \n    - The new `join_at` time must be in the future\n    - The bot must be in `scheduled` status\n    - The join time must be at least 4 minutes in the future (lock window)\n    - If the join time is too close, the request will fail with 409 Conflict\n    \n    **Status Requirements:** The bot must be in `scheduled` status. Bots that have already joined (`completed`) or failed (`failed`) cannot be updated. If the bot is in an invalid state, the request will fail with a 409 Conflict status.\n    \n    **Validation:** All updated fields are validated using the same rules as bot creation. Invalid configurations will result in a 400 Bad Request error.\n    \n    Returns 404 if the scheduled bot is not found, or 409 if the bot's status does not allow update or the join time is too close.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateScheduledBotRequestBodyInput"}}}},"parameters":[{"schema":{"type":"string","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)$"},"in":"path","name":"bot_id","required":true,"description":"The UUID of the scheduled bot to update.\n\nThis is the unique identifier returned when creating a scheduled bot.\n\nExample: \"123e4567-e89b-12d3-a456-426614174000\""}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateScheduledBotResponse"}}}},"400":{"description":"Bad Request - Invalid input or validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"404":{"description":"Not Found - Scheduled bot not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict - Bot status does not allow update or join time too close","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate Limited - Exceeded rate limit","content":{"application/json":{"schema":{"description":"Rate Limited - Exceeded rate limit","type":"object","properties":{"success":{"default":false,"type":"boolean","enum":[false]},"error":{"description":"Human-readable error message","type":"string"},"code":{"description":"Error code for programmatic handling","type":"string"},"statusCode":{"description":"HTTP status code","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"message":{"description":"Human-readable error message","anyOf":[{"type":"string"},{"type":"null"}]},"details":{"description":"Additional error details (string or null)","anyOf":[{"type":"string"},{"type":"null"}]},"retryAfter":{"description":"Number of seconds to wait before retrying","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["success","error","code","statusCode"],"additionalProperties":false}}}},"500":{"description":"Internal Server Error - Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"deleteScheduledBot","summary":"Delete scheduled bot","tags":["Bots"],"description":"Cancel and delete a scheduled bot.\n    \n    The bot must be in `scheduled` status and the join time must be at least 4 minutes in the future. This ensures the bot can be updated before it starts processing. Once deleted, the scheduled bot cannot be recovered.\n    \n    **Status Requirements:** The bot must be in `scheduled` status. Bots that have already joined (`completed`) or failed (`failed`) cannot be deleted via this endpoint. If the bot is in an invalid state, the request will fail with a 409 Conflict status.\n    \n    **Join Time Requirements:** The join time must be at least 4 minutes in the future. If the join time is too close, the request will fail with 409 Conflict. This ensures the bot can be cancelled before it starts processing.\n    \n    **Irreversible Operation:** Once a scheduled bot is deleted, it cannot be recovered. If you need to cancel a bot that is about to join, you should use the leave endpoint on the actual bot instance instead.\n    \n    **No Token Impact:** Since tokens are not reserved for scheduled bots, deleting a scheduled bot does not affect your token balance.\n    \n    Returns 404 if the scheduled bot is not found, or 409 if the bot's status does not allow deletion or the join time is too close.","parameters":[{"schema":{"type":"string","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)$"},"in":"path","name":"bot_id","required":true,"description":"The UUID of the scheduled bot to cancel/delete.\n\nThis is the unique identifier returned when creating a scheduled bot.\n\nNote: This performs a soft delete (sets status to 'cancelled'). The bot must be in 'scheduled' status and the join_at time must be at least 10 minutes in the future.\n\nExample: \"123e4567-e89b-12d3-a456-426614174000\""}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteScheduledBotResponse"}}}},"400":{"description":"Bad Request - Invalid input or validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"404":{"description":"Not Found - Scheduled bot not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict - Bot status does not allow deletion or join time too close","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate Limited - Exceeded rate limit","content":{"application/json":{"schema":{"description":"Rate Limited - Exceeded rate limit","type":"object","properties":{"success":{"default":false,"type":"boolean","enum":[false]},"error":{"description":"Human-readable error message","type":"string"},"code":{"description":"Error code for programmatic handling","type":"string"},"statusCode":{"description":"HTTP status code","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"message":{"description":"Human-readable error message","anyOf":[{"type":"string"},{"type":"null"}]},"details":{"description":"Additional error details (string or null)","anyOf":[{"type":"string"},{"type":"null"}]},"retryAfter":{"description":"Number of seconds to wait before retrying","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["success","error","code","statusCode"],"additionalProperties":false}}}},"500":{"description":"Internal Server Error - Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v2/zoom-credentials":{"post":{"operationId":"createZoomCredential","summary":"Create a Zoom credential","tags":["Zoom Credentials"],"description":"Create a new Zoom credential for your team.\n\n    Zoom credentials store your Zoom OAuth App credentials (client_id and client_secret) securely encrypted. You can create two types of credentials:\n\n    **App-only credentials:** Provide only `name`, `client_id`, and `client_secret`. These credentials can be used for SDK authentication when bots join meetings.\n\n    **User-authorized credentials:** Additionally provide `authorization_code` and `redirect_uri`. The API will exchange the authorization code for OAuth tokens, enabling OBF (On-Behalf-Of) token support. OBF tokens allow bots to join meetings on behalf of a specific Zoom user.\n\n    **Security:** All credentials are encrypted at rest using AES-256-GCM. Client secrets and OAuth tokens are never returned in API responses.\n\n    **OAuth Flow:** To obtain an authorization code, redirect users to Zoom's OAuth authorization endpoint and capture the code from the callback. Ensure your redirect URI exactly matches the one registered in your Zoom OAuth App.\n\n    **Error Scenarios:**\n    - `400 Bad Request`: Invalid input or missing redirect_uri when authorization_code is provided\n    - `400 Bad Request`: Failed to exchange authorization code (invalid code or redirect_uri mismatch)","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"description":"A user-friendly name for the credential.\n\nThis name is for your reference and can be anything that helps you identify this credential. Names do not need to be unique.","example":"John Doe's Zoom Bot","type":"string","minLength":1,"maxLength":100},"client_id":{"description":"The Client ID from your Zoom OAuth App.\n\nFound in your Zoom Marketplace app under 'App Credentials'. This is used for SDK authentication when joining meetings.","example":"abcdefghijklmnopqrstuvwxyz123456","type":"string","minLength":1,"maxLength":256},"client_secret":{"description":"The Client Secret from your Zoom OAuth App.\n\nFound in your Zoom Marketplace app under 'App Credentials'. This will be encrypted at rest and never returned in API responses.","example":"secret123...","type":"string","minLength":1,"maxLength":256},"authorization_code":{"description":"OAuth authorization code obtained from Zoom OAuth flow.\n\nWhen provided, the API will exchange this code for access and refresh tokens, making this a 'user' type credential that supports OBF (On-Behalf-Of) tokens.\n\n**Important:** `redirect_uri` is required when providing an authorization code.","example":"authcode123...","type":"string","maxLength":2000},"redirect_uri":{"description":"The redirect URI used in the OAuth flow.\n\nMust exactly match the redirect URI registered in your Zoom OAuth App and used when obtaining the authorization code.","example":"https://yourapp.com/oauth/callback","type":"string","format":"uri"}},"required":["name","client_id","client_secret"]}}},"required":true},"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"credential_id":{"description":"The unique identifier (UUID) of the Zoom credential","example":"a1b2c3d4-e5f6-7890-abcd-ef1234567890","type":"string","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)$"},"name":{"description":"A user-friendly name for the credential.\n\nThis name is for your reference and can be anything that helps you identify this credential. Names do not need to be unique.","example":"John Doe's Zoom Bot","type":"string","minLength":1,"maxLength":100},"credential_type":{"description":"The type of Zoom credential.\n\n- `app`: SDK-only credentials (client_id and client_secret) for joining meetings\n- `user`: User-authorized credentials with OAuth tokens for OBF token support","example":"user","type":"string","enum":["app","user"]},"zoom_user_id":{"example":"user123","anyOf":[{"description":"The Zoom user ID associated with this credential.\n\nOnly present for 'user' type credentials. This is the Zoom user who authorized the OAuth app.","type":"string"},{"type":"null"}]},"zoom_account_id":{"example":"account456","anyOf":[{"description":"The Zoom account ID associated with this credential.\n\nOnly present for 'user' type credentials.","type":"string"},{"type":"null"}]},"scopes":{"example":"meeting:read,meeting:write,user:read","anyOf":[{"description":"The OAuth scopes granted to this credential.\n\nOnly present for 'user' type credentials. Comma-separated list of Zoom OAuth scopes.","type":"string"},{"type":"null"}]},"state":{"description":"The current state of the Zoom credential.\n\n- `active`: Credential is working and can be used\n- `invalid`: Credential has failed (tokens revoked, expired, etc.)","example":"active","type":"string","enum":["active","invalid"]},"last_error_message":{"example":null,"anyOf":[{"description":"The last error message from OBF token fetch attempts.\n\nThis is set when a bot fails to fetch an OBF token using this credential. It is cleared when a successful OBF token fetch occurs.","type":"string"},{"type":"null"}]},"last_error_at":{"example":null,"anyOf":[{"description":"When the last OBF token fetch error occurred (ISO 8601).\n\nCleared when a successful OBF token fetch occurs.","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"created_at":{"description":"When this credential was created (ISO 8601)","example":"2024-01-15T10:30:00Z","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"updated_at":{"description":"When this credential was last updated (ISO 8601)","example":"2024-01-15T10:30:00Z","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["credential_id","name","credential_type","zoom_user_id","zoom_account_id","scopes","state","last_error_message","last_error_at","created_at","updated_at"],"additionalProperties":false}},"required":["success","data"],"additionalProperties":false}}}},"400":{"description":"Bad Request - Invalid input or validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"429":{"description":"Rate Limited - Exceeded rate limit","content":{"application/json":{"schema":{"description":"Rate Limited - Exceeded rate limit","type":"object","properties":{"success":{"default":false,"type":"boolean","enum":[false]},"error":{"description":"Human-readable error message","type":"string"},"code":{"description":"Error code for programmatic handling","type":"string"},"statusCode":{"description":"HTTP status code","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"message":{"description":"Human-readable error message","anyOf":[{"type":"string"},{"type":"null"}]},"details":{"description":"Additional error details (string or null)","anyOf":[{"type":"string"},{"type":"null"}]},"retryAfter":{"description":"Number of seconds to wait before retrying","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["success","error","code","statusCode"],"additionalProperties":false}}}},"500":{"description":"Internal Server Error - Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"get":{"operationId":"listZoomCredentials","summary":"List Zoom credentials","tags":["Zoom Credentials"],"description":"List all Zoom credentials for your team.\n\n    Returns all non-deleted credentials with their metadata. Sensitive fields (client_secret, OAuth tokens) are never included in responses.\n\n    **Response Fields:**\n    - `credential_id`: UUID to reference this credential in bot requests\n    - `name`: User-friendly name for identification\n    - `credential_type`: \"app\" (SDK only) or \"user\" (with OAuth tokens)\n    - `zoom_user_id`: The Zoom user ID (only for \"user\" type)\n    - `state`: \"active\" or \"invalid\"\n    - `last_error_message`: Last OBF token fetch error (if any)\n\n    **Error Tracking:** If bots fail to fetch OBF tokens using a credential, the error is recorded in `last_error_message` and `last_error_at`. These fields are cleared on successful OBF token fetch.","responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"array","items":{"type":"object","properties":{"credential_id":{"description":"The unique identifier (UUID) of the Zoom credential","example":"a1b2c3d4-e5f6-7890-abcd-ef1234567890","type":"string","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)$"},"name":{"description":"A user-friendly name for the credential.\n\nThis name is for your reference and can be anything that helps you identify this credential. Names do not need to be unique.","example":"John Doe's Zoom Bot","type":"string","minLength":1,"maxLength":100},"credential_type":{"description":"The type of Zoom credential.\n\n- `app`: SDK-only credentials (client_id and client_secret) for joining meetings\n- `user`: User-authorized credentials with OAuth tokens for OBF token support","example":"user","type":"string","enum":["app","user"]},"zoom_user_id":{"example":"user123","anyOf":[{"description":"The Zoom user ID associated with this credential.\n\nOnly present for 'user' type credentials. This is the Zoom user who authorized the OAuth app.","type":"string"},{"type":"null"}]},"zoom_account_id":{"example":"account456","anyOf":[{"description":"The Zoom account ID associated with this credential.\n\nOnly present for 'user' type credentials.","type":"string"},{"type":"null"}]},"scopes":{"example":"meeting:read,meeting:write,user:read","anyOf":[{"description":"The OAuth scopes granted to this credential.\n\nOnly present for 'user' type credentials. Comma-separated list of Zoom OAuth scopes.","type":"string"},{"type":"null"}]},"state":{"description":"The current state of the Zoom credential.\n\n- `active`: Credential is working and can be used\n- `invalid`: Credential has failed (tokens revoked, expired, etc.)","example":"active","type":"string","enum":["active","invalid"]},"last_error_message":{"example":null,"anyOf":[{"description":"The last error message from OBF token fetch attempts.\n\nThis is set when a bot fails to fetch an OBF token using this credential. It is cleared when a successful OBF token fetch occurs.","type":"string"},{"type":"null"}]},"last_error_at":{"example":null,"anyOf":[{"description":"When the last OBF token fetch error occurred (ISO 8601).\n\nCleared when a successful OBF token fetch occurs.","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"created_at":{"description":"When this credential was created (ISO 8601)","example":"2024-01-15T10:30:00Z","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"updated_at":{"description":"When this credential was last updated (ISO 8601)","example":"2024-01-15T10:30:00Z","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["credential_id","name","credential_type","zoom_user_id","zoom_account_id","scopes","state","last_error_message","last_error_at","created_at","updated_at"],"additionalProperties":false}}},"required":["success","data"],"additionalProperties":false}}}},"400":{"description":"Bad Request - Invalid input or validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"429":{"description":"Rate Limited - Exceeded rate limit","content":{"application/json":{"schema":{"description":"Rate Limited - Exceeded rate limit","type":"object","properties":{"success":{"default":false,"type":"boolean","enum":[false]},"error":{"description":"Human-readable error message","type":"string"},"code":{"description":"Error code for programmatic handling","type":"string"},"statusCode":{"description":"HTTP status code","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"message":{"description":"Human-readable error message","anyOf":[{"type":"string"},{"type":"null"}]},"details":{"description":"Additional error details (string or null)","anyOf":[{"type":"string"},{"type":"null"}]},"retryAfter":{"description":"Number of seconds to wait before retrying","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["success","error","code","statusCode"],"additionalProperties":false}}}},"500":{"description":"Internal Server Error - Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v2/zoom-credentials/{id}":{"get":{"operationId":"getZoomCredential","summary":"Get a Zoom credential","tags":["Zoom Credentials"],"description":"Get detailed information about a specific Zoom credential.\n\n    Returns the credential's metadata including its current state and any recent errors. Sensitive fields (client_secret, OAuth tokens) are never included.\n\n    **Error Tracking:** The `last_error_message` and `last_error_at` fields show the most recent OBF token fetch failure. Check these fields if bots using this credential are failing to join meetings.\n\n    Returns 404 if the credential is not found or does not belong to your team.","parameters":[{"schema":{"example":"a1b2c3d4-e5f6-7890-abcd-ef1234567890","type":"string","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)$"},"in":"path","name":"id","required":true,"description":"The unique identifier (UUID) of the Zoom credential"}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"credential_id":{"description":"The unique identifier (UUID) of the Zoom credential","example":"a1b2c3d4-e5f6-7890-abcd-ef1234567890","type":"string","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)$"},"name":{"description":"A user-friendly name for the credential.\n\nThis name is for your reference and can be anything that helps you identify this credential. Names do not need to be unique.","example":"John Doe's Zoom Bot","type":"string","minLength":1,"maxLength":100},"credential_type":{"description":"The type of Zoom credential.\n\n- `app`: SDK-only credentials (client_id and client_secret) for joining meetings\n- `user`: User-authorized credentials with OAuth tokens for OBF token support","example":"user","type":"string","enum":["app","user"]},"zoom_user_id":{"example":"user123","anyOf":[{"description":"The Zoom user ID associated with this credential.\n\nOnly present for 'user' type credentials. This is the Zoom user who authorized the OAuth app.","type":"string"},{"type":"null"}]},"zoom_account_id":{"example":"account456","anyOf":[{"description":"The Zoom account ID associated with this credential.\n\nOnly present for 'user' type credentials.","type":"string"},{"type":"null"}]},"scopes":{"example":"meeting:read,meeting:write,user:read","anyOf":[{"description":"The OAuth scopes granted to this credential.\n\nOnly present for 'user' type credentials. Comma-separated list of Zoom OAuth scopes.","type":"string"},{"type":"null"}]},"state":{"description":"The current state of the Zoom credential.\n\n- `active`: Credential is working and can be used\n- `invalid`: Credential has failed (tokens revoked, expired, etc.)","example":"active","type":"string","enum":["active","invalid"]},"last_error_message":{"example":null,"anyOf":[{"description":"The last error message from OBF token fetch attempts.\n\nThis is set when a bot fails to fetch an OBF token using this credential. It is cleared when a successful OBF token fetch occurs.","type":"string"},{"type":"null"}]},"last_error_at":{"example":null,"anyOf":[{"description":"When the last OBF token fetch error occurred (ISO 8601).\n\nCleared when a successful OBF token fetch occurs.","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"created_at":{"description":"When this credential was created (ISO 8601)","example":"2024-01-15T10:30:00Z","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"updated_at":{"description":"When this credential was last updated (ISO 8601)","example":"2024-01-15T10:30:00Z","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["credential_id","name","credential_type","zoom_user_id","zoom_account_id","scopes","state","last_error_message","last_error_at","created_at","updated_at"],"additionalProperties":false}},"required":["success","data"],"additionalProperties":false}}}},"400":{"description":"Bad Request - Invalid input or validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"404":{"description":"Not Found - Zoom credential not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate Limited - Exceeded rate limit","content":{"application/json":{"schema":{"description":"Rate Limited - Exceeded rate limit","type":"object","properties":{"success":{"default":false,"type":"boolean","enum":[false]},"error":{"description":"Human-readable error message","type":"string"},"code":{"description":"Error code for programmatic handling","type":"string"},"statusCode":{"description":"HTTP status code","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"message":{"description":"Human-readable error message","anyOf":[{"type":"string"},{"type":"null"}]},"details":{"description":"Additional error details (string or null)","anyOf":[{"type":"string"},{"type":"null"}]},"retryAfter":{"description":"Number of seconds to wait before retrying","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["success","error","code","statusCode"],"additionalProperties":false}}}},"500":{"description":"Internal Server Error - Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"updateZoomCredential","summary":"Update a Zoom credential","tags":["Zoom Credentials"],"description":"Update an existing Zoom credential.\n\n    You can update the credential name, SDK credentials (client_id/client_secret), or re-authorize with new OAuth tokens.\n\n    **Updating Name:** Provide only `name` to rename the credential.\n\n    **Updating SDK Credentials:** Provide both `client_id` and `client_secret` together to update the SDK credentials.\n\n    **Re-authorizing:** Provide `authorization_code`, `redirect_uri`, `client_id`, and `client_secret` to exchange a new authorization code for fresh OAuth tokens. This also resets the credential state to \"active\" and clears any error messages.\n\n    **Error Scenarios:**\n    - `400 Bad Request`: Missing redirect_uri when authorization_code is provided\n    - `400 Bad Request`: Failed to exchange authorization code\n    - `404 Not Found`: Credential not found or does not belong to your team","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"description":"A user-friendly name for the credential.\n\nThis name is for your reference and can be anything that helps you identify this credential. Names do not need to be unique.","example":"John Doe's Zoom Bot","type":"string","minLength":1,"maxLength":100},"client_id":{"description":"The Client ID from your Zoom OAuth App.\n\nFound in your Zoom Marketplace app under 'App Credentials'. This is used for SDK authentication when joining meetings.","example":"abcdefghijklmnopqrstuvwxyz123456","type":"string","minLength":1,"maxLength":256},"client_secret":{"description":"The Client Secret from your Zoom OAuth App.\n\nFound in your Zoom Marketplace app under 'App Credentials'. This will be encrypted at rest and never returned in API responses.","example":"secret123...","type":"string","minLength":1,"maxLength":256},"authorization_code":{"description":"OAuth authorization code obtained from Zoom OAuth flow.\n\nWhen provided, the API will exchange this code for access and refresh tokens, making this a 'user' type credential that supports OBF (On-Behalf-Of) tokens.\n\n**Important:** `redirect_uri` is required when providing an authorization code.","example":"authcode123...","type":"string","maxLength":2000},"redirect_uri":{"description":"The redirect URI used in the OAuth flow.\n\nMust exactly match the redirect URI registered in your Zoom OAuth App and used when obtaining the authorization code.","example":"https://yourapp.com/oauth/callback","type":"string","format":"uri"}}}}}},"parameters":[{"schema":{"example":"a1b2c3d4-e5f6-7890-abcd-ef1234567890","type":"string","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)$"},"in":"path","name":"id","required":true,"description":"The unique identifier (UUID) of the Zoom credential"}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"credential_id":{"description":"The unique identifier (UUID) of the Zoom credential","example":"a1b2c3d4-e5f6-7890-abcd-ef1234567890","type":"string","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)$"},"name":{"description":"A user-friendly name for the credential.\n\nThis name is for your reference and can be anything that helps you identify this credential. Names do not need to be unique.","example":"John Doe's Zoom Bot","type":"string","minLength":1,"maxLength":100},"credential_type":{"description":"The type of Zoom credential.\n\n- `app`: SDK-only credentials (client_id and client_secret) for joining meetings\n- `user`: User-authorized credentials with OAuth tokens for OBF token support","example":"user","type":"string","enum":["app","user"]},"zoom_user_id":{"example":"user123","anyOf":[{"description":"The Zoom user ID associated with this credential.\n\nOnly present for 'user' type credentials. This is the Zoom user who authorized the OAuth app.","type":"string"},{"type":"null"}]},"zoom_account_id":{"example":"account456","anyOf":[{"description":"The Zoom account ID associated with this credential.\n\nOnly present for 'user' type credentials.","type":"string"},{"type":"null"}]},"scopes":{"example":"meeting:read,meeting:write,user:read","anyOf":[{"description":"The OAuth scopes granted to this credential.\n\nOnly present for 'user' type credentials. Comma-separated list of Zoom OAuth scopes.","type":"string"},{"type":"null"}]},"state":{"description":"The current state of the Zoom credential.\n\n- `active`: Credential is working and can be used\n- `invalid`: Credential has failed (tokens revoked, expired, etc.)","example":"active","type":"string","enum":["active","invalid"]},"last_error_message":{"example":null,"anyOf":[{"description":"The last error message from OBF token fetch attempts.\n\nThis is set when a bot fails to fetch an OBF token using this credential. It is cleared when a successful OBF token fetch occurs.","type":"string"},{"type":"null"}]},"last_error_at":{"example":null,"anyOf":[{"description":"When the last OBF token fetch error occurred (ISO 8601).\n\nCleared when a successful OBF token fetch occurs.","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"created_at":{"description":"When this credential was created (ISO 8601)","example":"2024-01-15T10:30:00Z","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"updated_at":{"description":"When this credential was last updated (ISO 8601)","example":"2024-01-15T10:30:00Z","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["credential_id","name","credential_type","zoom_user_id","zoom_account_id","scopes","state","last_error_message","last_error_at","created_at","updated_at"],"additionalProperties":false}},"required":["success","data"],"additionalProperties":false}}}},"400":{"description":"Bad Request - Invalid input or validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"404":{"description":"Not Found - Zoom credential not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate Limited - Exceeded rate limit","content":{"application/json":{"schema":{"description":"Rate Limited - Exceeded rate limit","type":"object","properties":{"success":{"default":false,"type":"boolean","enum":[false]},"error":{"description":"Human-readable error message","type":"string"},"code":{"description":"Error code for programmatic handling","type":"string"},"statusCode":{"description":"HTTP status code","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"message":{"description":"Human-readable error message","anyOf":[{"type":"string"},{"type":"null"}]},"details":{"description":"Additional error details (string or null)","anyOf":[{"type":"string"},{"type":"null"}]},"retryAfter":{"description":"Number of seconds to wait before retrying","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["success","error","code","statusCode"],"additionalProperties":false}}}},"500":{"description":"Internal Server Error - Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"deleteZoomCredential","summary":"Delete a Zoom credential","tags":["Zoom Credentials"],"description":"Delete a Zoom credential (soft delete).\n\n    The credential is marked as deleted and will no longer appear in list responses. Bots currently using this credential will fail to fetch OBF tokens.\n\n    **Impact on Bots:** If bots are configured to use this credential (via `zoom_config.credential_id`), they will fail with an error when trying to fetch OBF tokens. Make sure to update any bot configurations before deleting a credential.\n\n    **Soft Delete:** The credential is soft-deleted and can potentially be restored by support if needed. All associated encrypted data remains in the database.\n\n    Returns 404 if the credential is not found or does not belong to your team.","parameters":[{"schema":{"example":"a1b2c3d4-e5f6-7890-abcd-ef1234567890","type":"string","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)$"},"in":"path","name":"id","required":true,"description":"The unique identifier (UUID) of the Zoom credential"}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"message":{"description":"Success message","example":"Zoom credential deleted successfully","type":"string"}},"required":["message"],"additionalProperties":false}},"required":["success","data"],"additionalProperties":false}}}},"400":{"description":"Bad Request - Invalid input or validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"404":{"description":"Not Found - Zoom credential not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate Limited - Exceeded rate limit","content":{"application/json":{"schema":{"description":"Rate Limited - Exceeded rate limit","type":"object","properties":{"success":{"default":false,"type":"boolean","enum":[false]},"error":{"description":"Human-readable error message","type":"string"},"code":{"description":"Error code for programmatic handling","type":"string"},"statusCode":{"description":"HTTP status code","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"message":{"description":"Human-readable error message","anyOf":[{"type":"string"},{"type":"null"}]},"details":{"description":"Additional error details (string or null)","anyOf":[{"type":"string"},{"type":"null"}]},"retryAfter":{"description":"Number of seconds to wait before retrying","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["success","error","code","statusCode"],"additionalProperties":false}}}},"500":{"description":"Internal Server Error - Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v2/calendars/list-raw":{"post":{"operationId":"listRawCalendars","summary":"List raw calendars (preview before creating connection)","tags":["Calendars"],"description":"Preview available calendars from a Google or Microsoft account before creating a connection.\n    \n    Requires OAuth credentials (client ID, client secret, refresh token) to authenticate and list calendars. This endpoint does not create a connection - it only lists the calendars that are available for the given OAuth credentials. Useful for allowing users to select which calendars to sync.\n    \n    **OAuth Credentials:** You must provide valid OAuth credentials for the calendar provider. The endpoint will use the refresh token to obtain an access token and list calendars. If the refresh token is invalid or expired, the request will fail with 401 Unauthorized.\n    \n    **Calendar Information:** Returns a list of calendars with their IDs, names, descriptions, and whether they are primary calendars. Calendar IDs differ between providers (Google uses email-like IDs, Microsoft uses GUIDs).\n    \n    **Use Case:** This endpoint is typically called before creating a calendar connection to show users which calendars are available. Users can then select which calendars they want to sync.\n    \n    Returns 401 if OAuth token refresh failed, or 403 if a Microsoft account license is required.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListRawCalendarsRequestBodyInput"}}}},"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListRawCalendarsResponse"}}}},"400":{"description":"Bad Request - Invalid input or validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"401":{"description":"Unauthorized - OAuth token refresh failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Microsoft account license required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate Limited - Exceeded rate limit","content":{"application/json":{"schema":{"description":"Rate Limited - Exceeded rate limit","type":"object","properties":{"success":{"default":false,"type":"boolean","enum":[false]},"error":{"description":"Human-readable error message","type":"string"},"code":{"description":"Error code for programmatic handling","type":"string"},"statusCode":{"description":"HTTP status code","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"message":{"description":"Human-readable error message","anyOf":[{"type":"string"},{"type":"null"}]},"details":{"description":"Additional error details (string or null)","anyOf":[{"type":"string"},{"type":"null"}]},"retryAfter":{"description":"Number of seconds to wait before retrying","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["success","error","code","statusCode"],"additionalProperties":false}}}},"500":{"description":"Internal Server Error - Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v2/calendars":{"post":{"operationId":"createCalendarConnection","summary":"Create calendar connection","tags":["Calendars"],"description":"Connect a Google or Microsoft calendar to your account.\n    \n    The connection will automatically sync events and create push subscriptions for real-time updates. You must provide your own OAuth credentials (client ID, secret, refresh token). Once connected, the calendar will be synced immediately, and webhook subscriptions will be created for real-time event updates.\n    \n    **OAuth Credentials:** You must provide valid OAuth credentials for the calendar provider. The endpoint will validate the credentials by attempting to refresh the access token. If the refresh token is invalid or expired, the request will fail with 401 Unauthorized.\n    \n    **Initial Sync:** After creating the connection, an initial sync is performed automatically. This fetches all events from the calendar provider. The sync may take a few minutes for calendars with many events.\n    \n    **Push Subscriptions:** A push subscription is created automatically for real-time event updates. The subscription will send webhooks when events are created, updated, or cancelled.\n    \n    **Calendar Limits:** There may be limits on the number of calendar connections per team. If the limit is exceeded, the request will fail with 429 Status Code.\n    \n    **Duplicate Connections:** If a connection already exists for the same calendar ID and team, the request will fail with 409 Conflict. You can update an existing connection using the PATCH endpoint instead.\n    \n    Returns 201 with the newly created calendar connection. Returns 401 if OAuth token refresh failed, 429 if the calendar connection limit is exceeded, or 409 if the connection already exists.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCalendarConnectionRequestBodyInput"}}}},"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCalendarConnectionResponse"}}}},"400":{"description":"Bad Request - Invalid input or validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"401":{"description":"Unauthorized - OAuth token refresh failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict - Calendar connection already exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate Limited - Exceeded rate limit","content":{"application/json":{"schema":{"description":"Rate Limited - Exceeded rate limit","type":"object","properties":{"success":{"default":false,"type":"boolean","enum":[false]},"error":{"description":"Human-readable error message","type":"string"},"code":{"description":"Error code for programmatic handling","type":"string"},"statusCode":{"description":"HTTP status code","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"message":{"description":"Human-readable error message","anyOf":[{"type":"string"},{"type":"null"}]},"details":{"description":"Additional error details (string or null)","anyOf":[{"type":"string"},{"type":"null"}]},"retryAfter":{"description":"Number of seconds to wait before retrying","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["success","error","code","statusCode"],"additionalProperties":false}}}},"500":{"description":"Internal Server Error - Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"get":{"operationId":"listCalendars","summary":"List calendar connections","tags":["Calendars"],"description":"Retrieve a paginated list of calendar connections.\n    \n    Supports filtering by calendar platform (google, microsoft) and connection status (active, error, revoked, permission_denied). Results are ordered by creation date (newest first). Use cursor-based pagination for efficient navigation.\n    \n    **Pagination:** Uses cursor-based pagination. Provide a `cursor` query parameter to fetch the next page. The `limit` parameter controls how many results are returned per page (default: 50, max: 250).\n    \n    **Filtering:**\n    - `platform`: Filter by calendar platform (google, microsoft)\n    - `status`: Filter by connection status (active, error, revoked, permission_denied)\n    \n    **Connection Status:**\n    - `active`: Connection is working and syncing events\n    - `error`: Connection has errors (OAuth token refresh failed, etc.)\n    - `revoked`: OAuth access was revoked by the user\n    - `permission_denied`: Insufficient permissions for the OAuth scopes\n    \n    Returns a paginated list of calendar connections with metadata including calendar ID, platform, account email, status, and last sync time.","parameters":[{"schema":{"default":50,"type":"integer","minimum":1,"maximum":250},"in":"query","name":"limit","required":true,"description":"Maximum number of calendars to return in a single request.\n\nLimits the number of results returned in a single API call.\n\nDefault: 50 Minimum: 1 Maximum: 250"},{"schema":{"example":null,"default":null,"anyOf":[{"type":"string"},{"type":"null"}]},"in":"query","name":"cursor","required":false,"description":"The cursor to use for pagination.\n\nObtained from the `cursor` or `prev_cursor` field in the previous response.\n\nThe cursor is a base64-encoded string containing `<isoDate>::<id>`. To paginate backward, prefix the cursor with a `-` (minus sign).\n\nLeave as `null` to get the first page of results.\n\nExample: \"MjAyNS0wMS0xNVQxMDozMDowMFo6OjEyMzQ1\" or \"LU1qQXlOM1UxTmpVME5qVXhNakUwTkRrPQ==\" (for backward pagination)"},{"schema":{"example":null,"default":null,"anyOf":[{"type":"string"},{"type":"null"}]},"in":"query","name":"account_email","required":false,"description":"Filter calendars by account email address. This performs a case-insensitive partial match (ilike) on the email address associated with the calendar account.\n\nExample: \"example\" would match all calendars with email addresses containing \"example\" (e.g., \"example@domain.com\", \"user@example.com\")."},{"schema":{"example":null,"anyOf":[{"anyOf":[{"type":"string"},{"type":"null"}]},{"type":"null"}]},"in":"query","name":"calendar_platform","required":false,"description":"Filter calendars by platform. It can be used to find calendars that are associated with a specific platform. Valid values are: \"google\", \"microsoft\".\n\nExample: \"google\" would match all Google Calendar connections.\n\nTo filter multiple platforms, use a comma-separated list of values. For example, \"google,microsoft\" would match all calendars from both platforms."},{"schema":{"anyOf":[{"anyOf":[{"type":"string"},{"type":"null"}]},{"type":"null"}]},"in":"query","name":"status","required":false,"description":"Filter calendars by connection status(es). It can be used to find calendars that have any of the specified statuses. Valid values are one or more of: active, error, revoked, permission_denied.\n\nExample: \"active,error\" would match all calendars that are active or have errors.\n\nTo filter multiple statuses, use a comma-separated list of values."}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListCalendarsResponse"}}}},"400":{"description":"Bad Request - Invalid input or validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"429":{"description":"Rate Limited - Exceeded rate limit","content":{"application/json":{"schema":{"description":"Rate Limited - Exceeded rate limit","type":"object","properties":{"success":{"default":false,"type":"boolean","enum":[false]},"error":{"description":"Human-readable error message","type":"string"},"code":{"description":"Error code for programmatic handling","type":"string"},"statusCode":{"description":"HTTP status code","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"message":{"description":"Human-readable error message","anyOf":[{"type":"string"},{"type":"null"}]},"details":{"description":"Additional error details (string or null)","anyOf":[{"type":"string"},{"type":"null"}]},"retryAfter":{"description":"Number of seconds to wait before retrying","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["success","error","code","statusCode"],"additionalProperties":false}}}},"500":{"description":"Internal Server Error - Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v2/calendars/{calendar_id}":{"get":{"operationId":"getCalendarDetails","summary":"Get calendar connection details","tags":["Calendars"],"description":"Retrieve detailed information about a specific calendar connection.\n    \n    Returns the calendar connection's configuration, sync status, subscription status, and last sync time. Includes information about the OAuth credentials (without exposing sensitive data) and the calendar's metadata.\n    \n    **Sync Status:** The response includes the last sync time and whether the connection is actively syncing. If the connection has errors, the error information is included.\n    \n    **Subscription Status:** Includes information about the push subscription, including when it was created and when it expires. Subscriptions expire after a certain period and need to be renewed using the resubscribe endpoint.\n    \n    **Calendar Metadata:** Includes the calendar's ID, name, platform, and account email. This information is fetched from the calendar provider during the initial sync.\n    \n    Returns 404 if the calendar connection is not found or does not belong to your team.","parameters":[{"schema":{"type":"string","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)$"},"in":"path","name":"calendar_id","required":true,"description":"The unique identifier of the calendar to retrieve."}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetCalendarDetailsResponse"}}}},"400":{"description":"Bad Request - Invalid input or validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"404":{"description":"Not Found - Calendar connection not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate Limited - Exceeded rate limit","content":{"application/json":{"schema":{"description":"Rate Limited - Exceeded rate limit","type":"object","properties":{"success":{"default":false,"type":"boolean","enum":[false]},"error":{"description":"Human-readable error message","type":"string"},"code":{"description":"Error code for programmatic handling","type":"string"},"statusCode":{"description":"HTTP status code","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"message":{"description":"Human-readable error message","anyOf":[{"type":"string"},{"type":"null"}]},"details":{"description":"Additional error details (string or null)","anyOf":[{"type":"string"},{"type":"null"}]},"retryAfter":{"description":"Number of seconds to wait before retrying","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["success","error","code","statusCode"],"additionalProperties":false}}}},"500":{"description":"Internal Server Error - Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"deleteCalendarConnection","summary":"Delete calendar connection","tags":["Calendars"],"description":"Disconnect and delete a calendar connection.\n    \n    This will stop syncing events and remove all associated calendar data (events, event instances, series). The push subscription will be cancelled automatically. This operation is irreversible.\n    \n    **Data Deletion:** All calendar data associated with this connection will be deleted:\n    - Event series and instances\n    - Calendar bot schedules\n    - Sync history\n    \n    **Subscription Cancellation:** The push subscription is cancelled automatically when the connection is deleted. You will no longer receive webhooks for this calendar.\n    \n    **Irreversible Operation:** Once a calendar connection is deleted, it cannot be recovered. All associated data is permanently removed. If you need to reconnect the calendar, you must create a new connection.\n    \n    **Bot Schedules:** If there are active calendar bot schedules for events in this calendar, they will be cancelled when the connection is deleted. Bots that have already joined meetings will continue to function normally.\n    \n    Returns 200 with confirmation of deletion. Returns 404 if the calendar connection is not found or does not belong to your team.","parameters":[{"schema":{"type":"string","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)$"},"in":"path","name":"calendar_id","required":true,"description":"The unique identifier of the calendar to delete. This will stop syncing events and remove all scheduled bots for this calendar. It will also delete all event instances and remove the calendar"}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteCalendarConnectionResponse"}}}},"400":{"description":"Bad Request - Invalid input or validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"404":{"description":"Not Found - Calendar connection not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate Limited - Exceeded rate limit","content":{"application/json":{"schema":{"description":"Rate Limited - Exceeded rate limit","type":"object","properties":{"success":{"default":false,"type":"boolean","enum":[false]},"error":{"description":"Human-readable error message","type":"string"},"code":{"description":"Error code for programmatic handling","type":"string"},"statusCode":{"description":"HTTP status code","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"message":{"description":"Human-readable error message","anyOf":[{"type":"string"},{"type":"null"}]},"details":{"description":"Additional error details (string or null)","anyOf":[{"type":"string"},{"type":"null"}]},"retryAfter":{"description":"Number of seconds to wait before retrying","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["success","error","code","statusCode"],"additionalProperties":false}}}},"500":{"description":"Internal Server Error - Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"updateCalendarConnection","summary":"Update calendar connection","tags":["Calendars"],"description":"Update a calendar connection with new OAuth credentials.\n    \n    Useful when refresh tokens expire or credentials need to be rotated. The connection will be validated and a new push subscription will be created. The old subscription will be cancelled automatically.\n    \n    **OAuth Credentials:** You can update the client ID, client secret, and refresh token. All fields are optional - only provided fields will be updated. The endpoint will validate the new credentials by attempting to refresh the access token.\n    \n    **Validation:** After updating credentials, the connection is validated by attempting to refresh the access token. If the refresh fails, the connection status is updated to `error` and the request may fail with 401 Unauthorized.\n    \n    **Subscription Renewal:** A new push subscription is created automatically after updating credentials. The old subscription is cancelled to prevent duplicate webhooks.\n    \n    **Use Cases:**\n    - Refresh token expired and needs to be renewed\n    - OAuth credentials rotated for security\n    - Fixing connection errors by updating credentials\n    \n    Returns 200 with the updated calendar connection. Returns 401 if OAuth token refresh failed, 403 if permission is denied, or 404 if the calendar connection is not found.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCalendarConnectionRequestBodyInput"}}}},"parameters":[{"schema":{"type":"string","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)$"},"in":"path","name":"calendar_id","required":true,"description":"The unique identifier of the calendar to update."}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCalendarConnectionResponse"}}}},"400":{"description":"Bad Request - Invalid input or validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"401":{"description":"Unauthorized - OAuth token refresh failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Permission denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not Found - Calendar connection not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate Limited - Exceeded rate limit","content":{"application/json":{"schema":{"description":"Rate Limited - Exceeded rate limit","type":"object","properties":{"success":{"default":false,"type":"boolean","enum":[false]},"error":{"description":"Human-readable error message","type":"string"},"code":{"description":"Error code for programmatic handling","type":"string"},"statusCode":{"description":"HTTP status code","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"message":{"description":"Human-readable error message","anyOf":[{"type":"string"},{"type":"null"}]},"details":{"description":"Additional error details (string or null)","anyOf":[{"type":"string"},{"type":"null"}]},"retryAfter":{"description":"Number of seconds to wait before retrying","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["success","error","code","statusCode"],"additionalProperties":false}}}},"500":{"description":"Internal Server Error - Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v2/calendars/{calendar_id}/sync":{"post":{"operationId":"syncCalendar","summary":"Sync calendar events","tags":["Calendars"],"description":"Manually trigger a sync of calendar events.\n    \n    This will fetch all events from the calendar provider and update the calendar data. Events are normally synced automatically via push subscriptions, but you can use this endpoint to force a sync (e.g., after fixing connection errors or when you need immediate updates).\n    \n    **Sync Process:** The sync process fetches all events from the calendar provider. New events are added, updated events are modified, and cancelled events are marked as deleted. The sync may take a few minutes for calendars with many events.\n    \n    **Incremental vs Full Sync:** The endpoint performs a full sync, fetching all events from the calendar. Incremental syncs happen automatically via push subscriptions when events are created, updated, or cancelled.\n    \n    **Use Cases:**\n    - Force a sync after fixing connection errors\n    - Get immediate updates without waiting for push notifications\n    - Recover from missed push notifications\n    - Initial sync after creating a connection (though this happens automatically)\n    \n    **Response:** The response includes information about the sync operation, including how many events were synced. The actual event data is available via the list events endpoint.\n    \n    Returns 200 with sync results. Returns 401 if OAuth token refresh failed, or 404 if the calendar connection is not found.","parameters":[{"schema":{"type":"string","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)$"},"in":"path","name":"calendar_id","required":true,"description":"The unique identifier of the calendar to sync. This will fetch the latest events from the calendar provider and update the materialized instances (for the next 30 days)."}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncCalendarResponse"}}}},"400":{"description":"Bad Request - Invalid input or validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"401":{"description":"Unauthorized - OAuth token refresh failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not Found - Calendar connection not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate Limited - Exceeded rate limit","content":{"application/json":{"schema":{"description":"Rate Limited - Exceeded rate limit","type":"object","properties":{"success":{"default":false,"type":"boolean","enum":[false]},"error":{"description":"Human-readable error message","type":"string"},"code":{"description":"Error code for programmatic handling","type":"string"},"statusCode":{"description":"HTTP status code","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"message":{"description":"Human-readable error message","anyOf":[{"type":"string"},{"type":"null"}]},"details":{"description":"Additional error details (string or null)","anyOf":[{"type":"string"},{"type":"null"}]},"retryAfter":{"description":"Number of seconds to wait before retrying","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["success","error","code","statusCode"],"additionalProperties":false}}}},"500":{"description":"Internal Server Error - Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v2/calendars/{calendar_id}/resubscribe":{"post":{"operationId":"resubscribeCalendar","summary":"Resubscribe to calendar webhooks","tags":["Calendars"],"description":"Renew or recreate the push subscription for a calendar connection.\n    \n    Useful when subscriptions expire or need to be refreshed. A new subscription will be created and the old one will be cancelled. Subscriptions expire after a certain period (3 days for Microsoft, longer for Google) and need to be renewed periodically.\n    \n    **Subscription Renewal:** The endpoint creates a new push subscription with the calendar provider. The old subscription is cancelled to prevent duplicate webhooks. The new subscription will send webhooks for all calendar events (created, updated, cancelled).\n    \n    **Subscription Expiration:** Subscriptions expire automatically after a certain period:\n    - Microsoft: 3 days maximum\n    - Google: Longer period (varies)\n    \n    When a subscription expires, you will stop receiving webhook notifications. Use this endpoint to renew the subscription before it expires.\n    \n    **Use Cases:**\n    - Subscription is about to expire\n    - Subscription has expired and webhooks stopped working\n    - Need to refresh subscription for troubleshooting\n    \n    **Response:** The response includes information about the new subscription, including when it was created and when it expires.\n    \n    Returns 200 with subscription information. Returns 401 if OAuth token refresh failed, 403 if permission is denied, or 404 if the calendar connection is not found.","parameters":[{"schema":{"type":"string","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)$"},"in":"path","name":"calendar_id","required":true,"description":"The unique identifier of the calendar to sync. This will fetch the latest events from the calendar provider and update the materialized instances (for the next 30 days)."}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResubscribeCalendarResponse"}}}},"400":{"description":"Bad Request - Invalid input or validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"401":{"description":"Unauthorized - OAuth token refresh failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Permission denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not Found - Calendar connection not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate Limited - Exceeded rate limit","content":{"application/json":{"schema":{"description":"Rate Limited - Exceeded rate limit","type":"object","properties":{"success":{"default":false,"type":"boolean","enum":[false]},"error":{"description":"Human-readable error message","type":"string"},"code":{"description":"Error code for programmatic handling","type":"string"},"statusCode":{"description":"HTTP status code","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"message":{"description":"Human-readable error message","anyOf":[{"type":"string"},{"type":"null"}]},"details":{"description":"Additional error details (string or null)","anyOf":[{"type":"string"},{"type":"null"}]},"retryAfter":{"description":"Number of seconds to wait before retrying","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["success","error","code","statusCode"],"additionalProperties":false}}}},"500":{"description":"Internal Server Error - Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v2/calendars/{calendar_id}/events":{"get":{"operationId":"listEvents","summary":"List calendar events","tags":["Calendars"],"description":"Retrieve a paginated list of calendar events.\n    \n    Supports filtering by date range, status (confirmed, cancelled, tentative), and whether events are deleted. Results include whether a bot is scheduled for each event. Use cursor-based pagination for efficient navigation.\n    \n    **Pagination:** Uses cursor-based pagination. Provide a `cursor` query parameter to fetch the next page. The `limit` parameter controls how many results are returned per page (default: 50, max: 250).\n    \n    **Filtering:**\n    - `start_after`: ISO 8601 timestamp - only return events starting after this time\n    - `start_before`: ISO 8601 timestamp - only return events starting before this time\n    - `status`: Filter by event status (confirmed, cancelled, tentative)\n    - `include_deleted`: Include deleted events in results (default: false)\n    \n    **Event Information:** Each event includes its ID, title, start/end times, status, meeting URL (if available), meeting platform (if detected), and whether a bot is scheduled for the event.\n    \n    **Bot Scheduling:** The `bot_scheduled` field indicates whether a calendar bot schedule exists for this event. This does not mean the bot has joined - it means a bot is scheduled to join when the event starts.\n    \n    Returns a paginated list of calendar events with metadata.","parameters":[{"schema":{"default":50,"type":"integer","minimum":1,"maximum":250},"in":"query","name":"limit","required":true,"description":"Maximum number of events to return in a single request.\n\nLimits the number of results returned in a single API call.\n\nDefault: 50 Minimum: 1 Maximum: 250"},{"schema":{"example":null,"default":null,"anyOf":[{"type":"string"},{"type":"null"}]},"in":"query","name":"cursor","required":false,"description":"The cursor to use for pagination.\n\nObtained from the `cursor` or `prev_cursor` field in the previous response.\n\nThe cursor is a base64-encoded string containing `<isoDate>::<id>`. To paginate backward, prefix the cursor with a `-` (minus sign).\n\nLeave as `null` to get the first page of results.\n\nExample: \"MjAyNS0wMS0xNVQxMDozMDowMFo6OjEyMzQ1\" or \"LU1qQXlOM1UxTmpVME5qVXhNakUwTkRrPQ==\" (for backward pagination)"},{"schema":{"example":null,"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"in":"query","name":"start_date","required":false,"description":"Filter events starting on or after this date/time (ISO 8601 format)."},{"schema":{"example":null,"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"in":"query","name":"end_date","required":false,"description":"Filter events ending on or before this date/time (ISO 8601 format)."},{"schema":{"example":null,"anyOf":[{"anyOf":[{"type":"string"},{"type":"null"}]},{"type":"null"}]},"in":"query","name":"status","required":false,"description":"Filter events by status(es). It can be used to find events that have any of the specified statuses. Valid values are one or more of: confirmed, cancelled, tentative.\n\nExample: \"confirmed,cancelled\" would match all events that are confirmed or cancelled.\n\nTo filter multiple statuses, use a comma-separated list of values."},{"schema":{"default":true,"type":"boolean"},"in":"query","name":"show_cancelled","required":true,"description":"Whether to include cancelled events in the results. When set to 'false', only non-cancelled events are returned. Default: true"},{"schema":{"type":"string","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)$"},"in":"path","name":"calendar_id","required":true,"description":"The unique identifier of the calendar to list events from."}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListEventsResponse"}}}},"400":{"description":"Bad Request - Invalid input or validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"429":{"description":"Rate Limited - Exceeded rate limit","content":{"application/json":{"schema":{"description":"Rate Limited - Exceeded rate limit","type":"object","properties":{"success":{"default":false,"type":"boolean","enum":[false]},"error":{"description":"Human-readable error message","type":"string"},"code":{"description":"Error code for programmatic handling","type":"string"},"statusCode":{"description":"HTTP status code","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"message":{"description":"Human-readable error message","anyOf":[{"type":"string"},{"type":"null"}]},"details":{"description":"Additional error details (string or null)","anyOf":[{"type":"string"},{"type":"null"}]},"retryAfter":{"description":"Number of seconds to wait before retrying","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["success","error","code","statusCode"],"additionalProperties":false}}}},"500":{"description":"Internal Server Error - Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v2/calendars/{calendar_id}/series":{"get":{"operationId":"listEventSeries","summary":"List event series","tags":["Calendars"],"description":"Retrieve a paginated list of event series (both one-off and recurring events).\n    \n    Each series includes its associated event instances. Supports filtering by event type (one_off, recurring) and whether series are deleted. Use cursor-based pagination for efficient navigation.\n    \n    **Pagination:** Uses cursor-based pagination. Provide a `cursor` query parameter to fetch the next page. The `limit` parameter controls how many results are returned per page (default: 50, max: 250).\n    \n    **Event Types:**\n    - `one_off`: Single events (not part of a recurring series)\n    - `recurring`: Events that are part of a recurring series\n    \n    **Series Information:** Each series includes its series ID, event type, whether a bot is scheduled for all occurrences (`series_bot_scheduled`), and an array of event instances. For one-off events, the instances array contains a single instance. For recurring events, it contains all instances that have been synced.\n    \n    **Filtering:**\n    - `event_type`: Filter by event type (one_off, recurring)\n    - `include_deleted`: Include deleted series in results (default: false)\n    \n    **Bot Scheduling:** The `series_bot_scheduled` field indicates whether a calendar bot schedule exists for all occurrences of this series. Individual instances may have different bot scheduling status.\n    \n    Returns a paginated list of event series with their instances.","parameters":[{"schema":{"default":50,"type":"integer","minimum":1,"maximum":250},"in":"query","name":"limit","required":true,"description":"Maximum number of event series to return in a single request.\n\nLimits the number of results returned in a single API call.\n\nDefault: 50 Minimum: 1 Maximum: 250"},{"schema":{"example":null,"default":null,"anyOf":[{"type":"string"},{"type":"null"}]},"in":"query","name":"cursor","required":false,"description":"The cursor to use for pagination.\n\nObtained from the `cursor` or `prev_cursor` field in the previous response.\n\nThe cursor is a base64-encoded string containing `<isoDate>::<id>`. To paginate backward, prefix the cursor with a `-` (minus sign).\n\nLeave as `null` to get the first page of results.\n\nExample: \"MjAyNS0wMS0xNVQxMDozMDowMFo6OjEyMzQ1\" or \"LU1qQXlOM1UxTmpVME5qVXhNakUwTkRrPQ==\" (for backward pagination)"},{"schema":{"anyOf":[{"anyOf":[{"type":"string"},{"type":"null"}]},{"type":"null"}]},"in":"query","name":"event_type","required":false,"description":"Filter event series by type(s). It can be used to find event series that have any of the specified types. Valid values are one or more of: one_off, recurring.\n\nExample: \"one_off,recurring\" would match all event series that are one-off or recurring.\n\nTo filter multiple types, use a comma-separated list of values."},{"schema":{"default":true,"type":"boolean"},"in":"query","name":"show_cancelled","required":true,"description":"Whether to include cancelled event instances in the results. When set to 'false', only non-cancelled event instances are returned. Note: This only affects event instances within series, not the series themselves. Default: true"},{"schema":{"type":"string","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)$"},"in":"path","name":"calendar_id","required":true,"description":"The unique identifier of the calendar to list event series from."}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListEventSeriesResponse"}}}},"400":{"description":"Bad Request - Invalid input or validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"429":{"description":"Rate Limited - Exceeded rate limit","content":{"application/json":{"schema":{"description":"Rate Limited - Exceeded rate limit","type":"object","properties":{"success":{"default":false,"type":"boolean","enum":[false]},"error":{"description":"Human-readable error message","type":"string"},"code":{"description":"Error code for programmatic handling","type":"string"},"statusCode":{"description":"HTTP status code","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"message":{"description":"Human-readable error message","anyOf":[{"type":"string"},{"type":"null"}]},"details":{"description":"Additional error details (string or null)","anyOf":[{"type":"string"},{"type":"null"}]},"retryAfter":{"description":"Number of seconds to wait before retrying","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["success","error","code","statusCode"],"additionalProperties":false}}}},"500":{"description":"Internal Server Error - Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v2/calendars/{calendar_id}/events/{event_id}":{"get":{"operationId":"getEventDetails","summary":"Get event details","tags":["Calendars"],"description":"Retrieve detailed information about a specific calendar event.\n    \n    Returns comprehensive event information including attendees, meeting URL, meeting platform, status, and whether a bot is scheduled. Returns deleted events as well (use the `include_deleted` parameter or check the `deleted_at` field).\n    \n    **Event Details:** Includes all event metadata:\n    - Title, description, location\n    - Start and end times (ISO 8601 timestamps)\n    - Status (confirmed, cancelled, tentative)\n    - Attendees list\n    - Meeting URL (if available)\n    - Meeting platform (if detected from URL)\n    - Whether it's an all-day event\n    - Whether it's an exception to a recurring series\n    \n    **Bot Scheduling:** The `bot_scheduled` field indicates whether a calendar bot schedule exists for this event. If the event is part of a recurring series, the `series_bot_scheduled` field indicates whether a bot is scheduled for all occurrences.\n    \n    **Deleted Events:** Deleted events are included in the response. Check the `deleted_at` field to determine if an event has been deleted. Deleted events may still have associated bot schedules if they were scheduled before deletion.\n    \n    Returns 404 if the event is not found or does not belong to the specified calendar.","parameters":[{"schema":{"type":"string","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)$"},"in":"path","name":"calendar_id","required":true,"description":"The unique identifier of the calendar that contains the event."},{"schema":{"type":"string","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)$"},"in":"path","name":"event_id","required":true,"description":"The unique identifier of the event to retrieve. This is a specific occurrence of an event (for recurring events) or the event itself (for one-time events)."}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetEventDetailsResponse"}}}},"400":{"description":"Bad Request - Invalid input or validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"404":{"description":"Not Found - Event not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate Limited - Exceeded rate limit","content":{"application/json":{"schema":{"description":"Rate Limited - Exceeded rate limit","type":"object","properties":{"success":{"default":false,"type":"boolean","enum":[false]},"error":{"description":"Human-readable error message","type":"string"},"code":{"description":"Error code for programmatic handling","type":"string"},"statusCode":{"description":"HTTP status code","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"message":{"description":"Human-readable error message","anyOf":[{"type":"string"},{"type":"null"}]},"details":{"description":"Additional error details (string or null)","anyOf":[{"type":"string"},{"type":"null"}]},"retryAfter":{"description":"Number of seconds to wait before retrying","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["success","error","code","statusCode"],"additionalProperties":false}}}},"500":{"description":"Internal Server Error - Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v2/calendars/{calendar_id}/bots":{"post":{"operationId":"createCalendarBot","summary":"Schedule bot for calendar event","tags":["Calendars"],"description":"Schedule a bot to automatically join a calendar event.\n    \n    You can schedule for all occurrences of a recurring event or specific event instances. The bot will use the meeting URL from the event. Returns partial success if some events fail to schedule (e.g., if a bot is already scheduled or if the event doesn't have a meeting URL).\n    \n    **Scheduling Options:**\n    - `series_id`: Schedule for all occurrences of a recurring series\n    - `event_id`: Schedule for a specific event instance\n    - `all_occurrences`: Schedule for all future occurrences (for recurring events)\n    \n    **Meeting URL Requirement:** The event must have a meeting URL. If the event doesn't have a meeting URL, the scheduling will fail for that event. The meeting platform is automatically detected from the URL.\n    \n    **Bot Configuration:** You can provide bot configuration (name, image, recording mode, transcription settings, etc.) that will be used for all scheduled bots. The configuration applies to all events you're scheduling for.\n    \n    **Partial Success:** If you're scheduling for multiple events (e.g., all occurrences of a series), some events may fail to schedule (e.g., if a bot is already scheduled). The response includes information about which events succeeded and which failed.\n    \n    **Token Reservation:** Tokens are NOT reserved at scheduling time. Token availability and daily bot cap are checked when each bot actually joins the meeting. If tokens are insufficient or the daily cap is reached at join time, the bot will fail with an appropriate error.\n    \n    **Status:** The calendar bot schedule starts in `scheduled` status and transitions to `completed` when the bot instance is created and queued to join. If the bot fails to join, it transitions to `failed` status.\n    \n    Returns 201 with scheduling results. Returns 404 if the event series or event is not found.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCalendarBotRequestBodyInput"}}}},"parameters":[{"schema":{"type":"string","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)$"},"in":"path","name":"calendar_id","required":true,"description":"The unique identifier of the calendar that contains the event."}],"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCalendarBotResponse"}}}},"400":{"description":"Bad Request - Invalid input or validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"404":{"description":"Not Found - Event series or event not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate Limited - Exceeded rate limit","content":{"application/json":{"schema":{"description":"Rate Limited - Exceeded rate limit","type":"object","properties":{"success":{"default":false,"type":"boolean","enum":[false]},"error":{"description":"Human-readable error message","type":"string"},"code":{"description":"Error code for programmatic handling","type":"string"},"statusCode":{"description":"HTTP status code","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"message":{"description":"Human-readable error message","anyOf":[{"type":"string"},{"type":"null"}]},"details":{"description":"Additional error details (string or null)","anyOf":[{"type":"string"},{"type":"null"}]},"retryAfter":{"description":"Number of seconds to wait before retrying","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["success","error","code","statusCode"],"additionalProperties":false}}}},"500":{"description":"Internal Server Error - Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"updateCalendarBot","summary":"Update calendar bot","tags":["Calendars"],"description":"Update one or more calendar bots for a calendar.\n    \n    You can target a single event or all occurrences in a series using `series_id`, `all_occurrences`, and `event_id` in the request body. The bot must be in `scheduled` status and the join time must be at least 4 minutes in the future.\n    \n    **Update Targets:**\n    - `event_id`: Update bot for a specific event instance\n    - `series_id`: Update bots for all occurrences of a series\n    - `all_occurrences`: Update all future occurrences (for recurring events)\n    \n    **Updateable Fields:** You can update any bot configuration field (bot name, image, recording mode, transcription settings, etc.). All fields are optional - only provided fields will be updated.\n    \n    **Status Requirements:** The bot must be in `scheduled` status. Bots that have already joined (`completed`) or failed (`failed`) cannot be updated. If the bot is in an invalid state, the request will fail with a 409 Conflict status.\n    \n    **Join Time Requirements:** The join time must be at least 4 minutes in the future. If the join time is too close, the request will fail with 409 Conflict. This ensures the bot can be updated before it starts processing.\n    \n    **Partial Updates:** If updating multiple bots (e.g., all occurrences of a series), some bots may fail to update (e.g., if they're not in `scheduled` status). The response includes information about which bots were updated and which failed.\n    \n    Returns 200 with update results. Returns 404 if the event or calendar bot schedule is not found, or 409 if the bot's status does not allow update.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCalendarBotRequestBodyInput"}}}},"parameters":[{"schema":{"type":"string","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)$"},"in":"path","name":"calendar_id","required":true,"description":"The unique identifier of the calendar that contains the event."}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCalendarBotResponse"}}}},"400":{"description":"Bad Request - Invalid input or validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"404":{"description":"Not Found - Event or calendar bot schedule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict - Bot status does not allow update","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate Limited - Exceeded rate limit","content":{"application/json":{"schema":{"description":"Rate Limited - Exceeded rate limit","type":"object","properties":{"success":{"default":false,"type":"boolean","enum":[false]},"error":{"description":"Human-readable error message","type":"string"},"code":{"description":"Error code for programmatic handling","type":"string"},"statusCode":{"description":"HTTP status code","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"message":{"description":"Human-readable error message","anyOf":[{"type":"string"},{"type":"null"}]},"details":{"description":"Additional error details (string or null)","anyOf":[{"type":"string"},{"type":"null"}]},"retryAfter":{"description":"Number of seconds to wait before retrying","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["success","error","code","statusCode"],"additionalProperties":false}}}},"500":{"description":"Internal Server Error - Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"deleteCalendarBot","summary":"Cancel calendar bot","tags":["Calendars"],"description":"Cancel one or more scheduled calendar bots.\n    \n    You can target a single event or all occurrences in a series using `series_id`, `all_occurrences`, and `event_id` in the request body. Bots must be in `scheduled` status and the join time must be at least 4 minutes in the future.\n    \n    **Cancellation Targets:**\n    - `event_id`: Cancel bot for a specific event instance\n    - `series_id`: Cancel bots for all occurrences of a series\n    - `all_occurrences`: Cancel all future occurrences (for recurring events)\n    \n    **Status Requirements:** Bots must be in `scheduled` status. Bots that have already joined (`completed`) or failed (`failed`) cannot be cancelled via this endpoint. If a bot is in an invalid state, that bot will fail to cancel, but other bots may still be cancelled.\n    \n    **Join Time Requirements:** The join time must be at least 4 minutes in the future. If the join time is too close, the request will fail with 409 Conflict. This ensures the bot can be updated before it starts processing.\n    \n    **Partial Cancellation:** If cancelling multiple bots (e.g., all occurrences of a series), some bots may fail to cancel (e.g., if they're not in `scheduled` status). The response includes information about which bots were cancelled and which failed.\n    \n    **Irreversible Operation:** Once a calendar bot is cancelled, it cannot be recovered. If you need to cancel a bot that is about to join, you should use the leave endpoint on the actual bot instance instead.\n    \n    **No Token Impact:** Since tokens are not reserved for calendar bots, cancelling a bot does not affect your token balance.\n    \n    Returns 200 with cancellation results. Returns 404 if the event or calendar bot schedule is not found, or 409 if the bot's status does not allow deletion.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"series_id":{"description":"The UUID of the event series to schedule bots for.\n\nBoth one-off and recurring events have a series_id. For recurring events, use 'all_occurrences' to schedule bots for all future occurrences.","type":"string","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)$"},"all_occurrences":{"description":"Whether to schedule bots for all occurrences of the event series.\n\nIf `true`, bots will be scheduled for all future event instances in the series. If `false`, `event_id` must be provided to schedule a bot for a specific event instance.\n\nDefault: `false`","default":false,"type":"boolean"},"event_id":{"description":"The UUID of a specific event instance to schedule a bot for.\n\nRequired when `all_occurrences` is `false`. Use this to schedule a bot for a single occurrence of a recurring event or a specific one-off event. If `all_occurrences` is `true`, this parameter is ignored.","example":null,"type":"string","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)$"}},"required":["series_id","all_occurrences"]}}},"required":true},"parameters":[{"schema":{"type":"string","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)$"},"in":"path","name":"calendar_id","required":true,"description":"The unique identifier of the calendar that contains the event."}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteCalendarBotResponse"}}}},"400":{"description":"Bad Request - Invalid input or validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"404":{"description":"Not Found - Event or calendar bot schedule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict - Bot status does not allow deletion","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate Limited - Exceeded rate limit","content":{"application/json":{"schema":{"description":"Rate Limited - Exceeded rate limit","type":"object","properties":{"success":{"default":false,"type":"boolean","enum":[false]},"error":{"description":"Human-readable error message","type":"string"},"code":{"description":"Error code for programmatic handling","type":"string"},"statusCode":{"description":"HTTP status code","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"message":{"description":"Human-readable error message","anyOf":[{"type":"string"},{"type":"null"}]},"details":{"description":"Additional error details (string or null)","anyOf":[{"type":"string"},{"type":"null"}]},"retryAfter":{"description":"Number of seconds to wait before retrying","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["success","error","code","statusCode"],"additionalProperties":false}}}},"500":{"description":"Internal Server Error - Unexpected server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}},"servers":[{"url":"https://api.meetingbaas.com","description":"production server"}],"security":[{"ApiKeyAuth":[]}],"tags":[{"name":"Bots","description":"Bot management endpoints for creating, listing, and managing meeting bots"},{"name":"Calendars","description":"Calendar integration endpoints for connecting calendars, managing events, and scheduling calendar bots"},{"name":"Webhooks","description":"Webhook event types that are sent to your webhook URL when bot or calendar events occur. Configure a webhook URL in your account settings or provide it when creating a bot."},{"name":"Callbacks","description":"Callbacks that are sent to your callback URL when the bot completes or fails. Configure a callback URL when creating a bot."}]}