Use this file to discover all available pages before exploring further.
Webhooks send your server real-time updates when something important happens in Attendee, so that you don’t need to poll the API.They can alert your server when a bot joins a meeting, starts recording, when a recording is available, when a chat message is sent, when the transcript is updated, when participants join or leave meetings, or when calendar events are updated.Attendee supports two types of webhooks:
Project-level webhooks: Apply to all bots in a project (created via UI)
Bot-level webhooks: Apply to specific bots only (created via API)
Provide an HTTPS URL that will receive webhook events
4
Select triggers
Select the triggers you want to receive notifications for (we currently have eight triggers: bot.state_change, transcript.update, chat_messages.update, participant_events.join_leave, participant_events.speech_start_stop, calendar.events_update, calendar.state_change, and bot_logs.update)
{ "idempotency_key": "< UUID that uniquely identifies this webhook delivery >", "bot_id": "< Id of the bot associated with the webhook delivery >", "bot_metadata": "< Any metadata associated with the bot >", "trigger": "< Trigger for the webhook >", "data": "< Trigger-specific data >"}
{ "idempotency_key": "< UUID that uniquely identifies this webhook delivery >", "calendar_id": "< Id of the calendar associated with the webhook delivery >", "calendar_deduplication_key": "< Deduplication key of the calendar (if set) >", "calendar_metadata": "< Any metadata associated with the calendar >", "trigger": "< Trigger for the webhook >", "data": "< Trigger-specific data >"}
For webhooks triggered by bot.state_change, the data field contains:
{ "new_state": "< The current state of the bot >", "old_state": "< The previous state of the bot >", "created_at": "< The timestamp when the state change occurred >", "event_type": "< The type of event that triggered the state change >", "event_sub_type": "< The sub-type of event that triggered the state change >"}
Using webhooks to know when the recording is available
The most common use case for webhooks is to be notified when the meeting has ended and the recording is available. You can do this by listening for the post_processing_completed event type.The data field will look like this:
For webhooks triggered by transcript.update, the data field contains a single utterance:
{ "speaker_name": "<The name of the speaker>", "speaker_uuid": "<The UUID of the speaker within the meeting>", "speaker_user_uuid": "<The UUID of the speaker's user account within the meeting platform>", "speaker_is_host": "<Whether the speaker is the host of the meeting>", "timestamp_ms": "<The timestamp of the utterance in milliseconds>", "duration_ms": "<The duration of the utterance in milliseconds>", "transcription": { "transcript": "<The utterance text>", "words": "<The word-level timestamps of the utterance if they exist>" }}
For webhooks triggered by chat_messages.update, the data field contains a single chat message:
{ "id": "<The ID of the chat message>", "to": "<Whether the message was sent to the bot or to everyone>", "text": "<The text of the chat message>", "timestamp": "<The timestamp of the chat message>", "sender_name": "<The name of the participant who sent the chat message>", "sender_uuid": "<The UUID of the participant who sent the chat message>", "timestamp_ms": "<The timestamp of the chat message in milliseconds>", "additional_data": "<Any additional data associated with the chat message>", "sender_user_uuid": "<The UUID of the participant's user account within the meeting platform>"}
Payload for participant_events.join_leave and participant_events.speech_start_stop triggers
For webhooks triggered by participant_events.join_leave and participant_events.speech_start_stop, the data field contains a single participant event:
{ "id": "<The ID of the participant event>", "participant_name": "<The name of the participant who joined or left the meeting>", "participant_uuid": "<The UUID of the participant who joined or left the meeting>", "participant_user_uuid": "<The UUID of the participant's user account within the meeting platform>", "participant_is_host": "<Whether the participant is the host of the meeting>", "event_type": "<The type of event that occurred. Either 'join', 'leave', 'speech_start', or 'speech_stop'>", "event_data": "<Any additional data associated with the event. This is empty for join and leave events>", "timestamp_ms": "<The timestamp of the event in milliseconds>"}
For webhooks triggered by calendar.events_update, the data field contains calendar sync information:
{ "state": "<The current state of the calendar connection ('connected' or 'disconnected')>", "connection_failure_data": "<Any error data if the calendar is disconnected, null if connected>", "last_successful_sync_at": "<The timestamp of the last successful calendar sync>", "last_attempted_sync_at": "<The timestamp of the last sync attempt>"}
This webhook is triggered after each successful calendar sync operation, which occurs automatically to keep your calendar events up to date with the remote calendar (Google Calendar or Microsoft Calendar). After receiving this webhook, you can fetch the calendar events from the Attendee API to get the latest events.
For webhooks triggered by calendar.state_change, the data field contains the same structure as calendar.events_update:
{ "state": "<The current state of the calendar connection ('connected' or 'disconnected')>", "connection_failure_data": "<Error details when the calendar becomes disconnected>", "last_successful_sync_at": "<The timestamp of the last successful calendar sync>", "last_attempted_sync_at": "<The timestamp of the last sync attempt>"}
This webhook is triggered when a calendar’s connection state changes, typically when authentication fails and the calendar becomes disconnected. The connection_failure_data field will contain error details such as:
For webhooks triggered by bot_logs.update, the data field contains information about a log entry associated with a bot:
{ "id": "<The ID of the log entry>", "level": "<The severity level of the log entry (e.g., 'debug', 'info', 'warning', 'error')>", "entry_type": "<The type of the log entry (e.g., 'uncategorized', 'could_not_enable_closed_captions')>", "message": "<The log message>", "created_at": "<The timestamp when the log entry was created>"}
This webhook fires every time a new log entry is recorded for a bot. Use these events to keep track of errors, warnings, or other relevant activities occurring on your bots — especially issues that matter but don’t rise to the level of a state change. Monitoring these log webhooks helps you catch and investigate noteworthy bot events in real time.
Go to the ‘Bots’ page and navigate to a Bot which was created after you created your webhook. You should see a ‘Webhooks’ tab on the page. Clicking it will show a list of all the webhook deliveries for that bot, whether they succeeded and the response from your server.
To ensure the webhook requests are coming from Attendee, we sign each request with a secret. You can verify this signature to confirm the authenticity of the request.
Each project has a single webhook secret used for both project and bot-level webhooks. You can get the secret in the Settings → Webhooks page.
The signature is included in the X-Webhook-Signature header of each webhook request
If your endpoint returns a non-2xx status code or fails to respond within 10 seconds, Attendee will retry the webhook delivery up to 3 times with exponential backoff.