If you don't want to build a meeting bot yourself, check out Recall.ai's Meeting Bot API. Recall.ai works across Zoom, Google Meet, Microsoft Teams, and more.
This is a starter Next.js app that sends a Recall.ai bot to an interview, records and transcribes the call, and (optionally) generates structured notes and a scorecard with timestamp links into the recording.
- Node.js 20.9 or later
- Ngrok (use a reserved domain so your webhook URL stays stable)
- Recall.ai API key and workspace verification secret (
whsec_…) — both are on the API keys page for your region: us-east-1 · us-west-2 · eu-central-1 · ap-northeast-1 - An OpenAI or Anthropic API key (optional — only needed for notes)
git clone https://github.com/recallai/interview-notetaker
cd interview-notetakernpm installCopy .env.example to .env and fill in your values. Each variable is explained in that file.
cp .env.example .envYou need RECALL_REGION, RECALL_API_KEY, and RECALL_WEBHOOK_SECRET. For notes, also set OPENAI_API_KEY, or set AI_PROVIDER=anthropic and ANTHROPIC_API_KEY.
RECALL_REGION will be one of us-east-1, us-west-2, eu-central-1, or ap-northeast-1. Check the URL when you're logged in to the Recall dashboard to confirm.
Connect the Recall.ai MCP so an agent can search docs and inspect bots, webhooks, and logs in your workspace. You can also give the agent write permissions to allow it to set up webhook endpoints for you automatically. This will allow your agent to do most of the setup for this sample application.
-
Start ngrok with your reserved domain (terminal 1):
ngrok http 3000 --domain=your-static-domain.ngrok-free.app
See our ngrok setup guide for static domains.
-
Start the development server (terminal 2):
npm run dev
-
Configure the webhook in the Recall.ai dashboard for your region. If you have configured an MCP API key with write permissions, the MCP can do this step for you! Simply ask it to set up an endpoint and subscribe to the relevant events in this repo.
- Endpoint: your ngrok URL followed by
/api/webhooks/recall, e.g.https://your-static-domain.ngrok-free.app/api/webhooks/recall - Subscribe to:
bot.joining_call,bot.in_waiting_room,bot.in_call_not_recording,bot.in_call_recording,bot.call_ended,bot.done,bot.fatalrecording.done,recording.failedtranscript.done,transcript.failed
- Endpoint: your ngrok URL followed by
-
Open your browser to http://localhost:3000
-
Paste a Zoom / Google Meet / Teams URL and send the notetaker
Note: This sample has no authentication, and ngrok exposes the whole app. Anyone with your ngrok URL can read your interviews and send bots billed to your Recall.ai account. Keep the URL private, and add authentication before deploying it anywhere.
The bot will join the meeting and the app will:
- Track join / waiting room / recording status from webhooks
- Request a transcript when recording starts (Recall.ai streaming + diarization)
- Show the recording and transcript when the call ends
- Generate timestamped notes (and an optional scorecard) if an AI API key is set
The status is stuck (e.g. "Joining call" after you admitted the bot). The app isn't receiving webhooks. Reloading the interview page asks Recall for the bot's latest state, so it catches up, but live updates need webhooks. In the Recall dashboard, check that your endpoint is active and that its URL ends in /api/webhooks/recall. Each delivery attempt shows the response your app returned; a 404 means the URL path is wrong, and a 401 means the verification secret doesn't match.
- src/lib/recall.ts: the Recall API client (with 429 / 503 / 507 retries) and the bot configuration: camera images, chat-on-join message, transcription settings, and
metadata.interview_id. - src/app/api/interviews/route.ts: send a bot now, or schedule one with
join_at. - src/app/api/interviews/[id]/control/route.ts: start, pause, resume, and leave. Pause and resume keep a single recording; stop then start would create a second one.
- src/lib/webhooks.ts: webhook signature verification, bot status updates,
recording.done, andtranscript.done, which downloads the transcript and starts notes. - src/lib/notes.ts: note and scorecard prompts.
Every Recall API call has a docs link above it. Search for recallJson( to find them all.
This app requests transcription on Create Bot instead of calling Create Async Transcript after the call. (With wait-for-consent on, it's requested on Start Recording instead.) The app waits for transcript.done, then downloads the transcript. Download URLs are presigned and expire, so the app fetches them when needed instead of storing them.