Webhook events
Every event type emitted in production, with the exact payload your endpoint will receive for each.
If an event is not on this page, it does not exist.
Event catalog
All current events belong to the meetings domain:
| Event | Fired when |
|---|---|
meeting.started | A meeting transitions to in-progress |
meeting.ended | A meeting completes |
meeting.cancelled | A meeting is cancelled |
participant.joined | A participant joins a meeting |
participant.left | A participant leaves a meeting |
recording.ready | A meeting recording becomes available |
transcript.ready | A meeting transcript becomes available |
Subscriptions are per endpoint: each registered endpoint declares which of these event types it receives. See webhooks for delivery mechanics.
Envelope
Every event shares the same envelope; only data varies:
{
"id": "evt-uuid",
"type": "meeting.started",
"timestamp": "2026-06-12T10:00:00Z",
"delivery_id": "delivery-uuid",
"organization_id": "org-uuid",
"data": { }
}Payloads by event
meeting.started / meeting.ended / meeting.cancelled
{
"meeting_id": "uuid",
"title": "Final interview — Senior Engineer",
"scheduled_start": "2026-06-12T10:00:00Z",
"scheduled_end": "2026-06-12T11:00:00Z",
"host_id": "uuid"
}participant.joined / participant.left
{
"meeting_id": "uuid",
"participant_id": "uuid",
"user_id": "uuid",
"name": "Alice Janssen",
"role": "participant",
"timestamp": "2026-06-12T10:02:14Z"
}user_id is omitted for guests. role is one of host, participant, guest, observer.
recording.ready
{
"meeting_id": "uuid",
"recording_id": "uuid",
"duration_seconds": 3120,
"size_bytes": 482344960,
"download_url": "https://…"
}transcript.ready
{
"meeting_id": "uuid",
"transcript_id": "uuid",
"language": "en",
"transcript_url": "https://…"
}Recordings and transcripts exist only for meetings where participants gave recording consent — see GDPR and data rights. Treat download_url and transcript_url as sensitive: they reference personal data and should not be logged or forwarded outside your processing pipeline.
Consumption notes
- Delivery is at-least-once and unordered — deduplicate on
delivery_idand do not infer sequence from arrival order. A retriedparticipant.joinedcan arrive after the matchingparticipant.left. - Use the envelope
timestamp(and the participant payload's owntimestamp) for ordering decisions. - New event types may be added over time. Ignore unrecognized
typevalues gracefully rather than failing the delivery; your endpoint only receives types it subscribed to, but a tolerant parser costs nothing.
There are no job.*, candidate.*, or offer.* webhook events today. Integrations that need hiring-pipeline data should not poll for event names that this page does not list.
Your consumer handles all seven meeting-domain events, deduplicates on delivery_id, and degrades gracefully on unknown types.

