Agent skill

Recall.ai Webhooks Skill

Receive and verify Recall.ai webhooks (meeting bot / recording API). Use when setting up Recall.ai webhook handlers, debugging webhook-signature or legacy svix-signature verification (Standard Webhooks, base64 HMAC-SHA256 over "<id>.<timestamp>.<raw body>" with a whsec_ secret), or handling events like bot.done, bot.fatal, bot.call_ended, recording.done, transcript.done, calendar.sync_events, participant_events.join or transcript.data.

Install this skill

npx skills add hookdeck/webhook-skills --skill recall-ai-webhooks


When to Use This Skill

  • How do I receive Recall.ai webhooks for meeting bot status changes?
  • How do I verify Recall.ai webhook signatures (webhook-signature or svix-signature)?
  • Why are the webhook-id / webhook-timestamp / webhook-signature headers missing?
  • Handling bot.done, recording.done or transcript.done to download media and transcripts
  • Handling real-time endpoint events like participant_events.join and transcript.data
  • Keeping bot scheduling in sync with Calendar V2 (calendar.update, calendar.sync_events)

Verification (core)

Recall.ai uses Standard Webhooks. With a workspace verification secret (Developers → API Keys & Secrets) every request carries webhook-id, webhook-timestamp and webhook-signature. Accounts created before 2025-12-15 get svix-id, svix-timestamp and svix-signature on Svix webhooks, signed with the per-endpoint Svix secret. The algorithm is the same, so accept either prefix:

const prefix = headers['webhook-signature'] !== undefined ? 'webhook' : 'svix';
const id = headers[`${prefix}-id`];
const timestamp = headers[`${prefix}-timestamp`];
const signature = headers[`${prefix}-signature`]; // "v1,<b64> v1,<b64>"

// Key = base64-decoded part after "whsec_"; signed content = id.timestamp.rawBody
const key = Buffer.from(secret.slice('whsec_'.length), 'base64');
const expected = crypto.createHmac('sha256', key)
  .update(`${id}.${timestamp}.`).update(rawBody).digest();

// Several signatures arrive after a secret rotation: accept any v1 match
const valid = signature.split(' ').some((entry) => {
  const [version, sig] = entry.split(',');
  if (version !== 'v1' || !sig) return false;
  const bytes = Buffer.from(sig, 'base64');
  return bytes.length === expected.length && crypto.timingSafeEqual(bytes, expected);
});

Verify the raw body, return 400 on failure, and optionally reject timestamps more than 5 minutes old (the examples do; Recall.ai's sample doesn't). There's no Recall.ai SDK for this; standardwebhooks or svix libraries also work.

For complete handlers with tests, see examples/express/, examples/nextjs/, examples/fastapi/.

Common Event Types

The event name is in the body's top-level event field (not type).

EventDeliveryDescription
bot.joining_callSvixBot is connecting to the meeting
bot.in_waiting_roomSvixBot is in the waiting room
bot.in_call_not_recordingSvixBot joined but isn't recording
bot.in_call_recordingSvixBot is recording
bot.call_endedSvixBot left the call; media may not be ready yet
bot.doneSvixBot shut down; recorded media is available
bot.fatalSvixBot failed (data.data.sub_code has the reason)
recording.done / recording.failedSvixRecording artifact finished or failed
transcript.done / transcript.failedSvixTranscript artifact finished or failed
calendar.updateSvixCalendar changed (e.g. disconnected); re-fetch it
calendar.sync_eventsSvixCalendar events changed since data.last_updated_ts
participant_events.join / participant_events.leaveReal-timeParticipant joined or left
transcript.dataReal-timeTranscript utterance generated during the call

For the full list (media artifacts like audio_mixed.done, breakout room events, all participant events), see references/overview.md.

Environment Variables

# Workspace verification secret, or the legacy Svix endpoint signing secret
RECALL_WEBHOOK_SECRET=whsec_xxxxx

Local Development

# Start tunnel (no account needed)
npx hookdeck-cli listen 3000 recall-ai --path /webhooks/recall-ai

Add the tunnel URL as an endpoint in your region's Recall.ai Webhooks dashboard (us-east-1, us-west-2, eu-central-1 or ap-northeast-1), or as a realtime_endpoints URL on Create Bot.

Reference Materials


Repository

hookdeck/webhook-skills

v0.1.0 · MIT · Updated Oct 28, 2026

View on GitHub →