Agent skill
Fathom Webhooks Skill
Receive and verify Fathom (fathom.video / fathom.ai) AI meeting notetaker webhooks. Use when setting up a Fathom webhook handler, debugging webhook-signature verification (Standard Webhooks, whsec_ secret), or processing the "new meeting content ready" payload with the meeting summary, transcript, and action items. Not for Fathom Analytics (usefathom.com).
Install this skill
npx skills add hookdeck/webhook-skills --skill fathom-webhooks
Fathom is an AI meeting notetaker. After a recorded meeting is processed, Fathom POSTs the meeting (optionally with its summary, transcript, action items and CRM matches) to your webhook URL. This skill covers Fathom the notetaker (fathom.video / developers.fathom.ai), not Fathom Analytics (usefathom.com).
When to Use This Skill
- How do I receive Fathom webhooks after a meeting is recorded?
- How do I verify Fathom webhook signatures (
webhook-signature)? - How do I get the Fathom meeting summary, transcript, or action items via webhook?
- Why is my Fathom webhook signature verification failing?
- Why isn't my Fathom webhook firing?
Verification (core)
Fathom uses Standard Webhooks. Every request carries webhook-id, webhook-timestamp (Unix seconds) and webhook-signature (space-delimited v1,<base64> list). The signature is base64(HMAC-SHA256) over {webhook-id}.{webhook-timestamp}.{raw body}, keyed with the base64-decoded part of your whsec_... secret.
The official SDKs wrap this in one call. It throws on a bad signature or a timestamp more than 5 minutes off, and returns the parsed payload:
import { Fathom } from 'fathom-typescript'; // Python: from fathom_python import Fathom
const meeting = Fathom.verifyWebhook(process.env.FATHOM_WEBHOOK_SECRET, headers, rawBody);
Manual equivalent (Node), if you can't use the SDK:
const crypto = require('crypto');
function verifyFathomWebhook(secret, id, timestamp, signatureHeader, rawBody) {
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;
const key = Buffer.from(secret.split('_')[1], 'base64'); // decode part after whsec_
const expected = crypto.createHmac('sha256', key)
.update(`${id}.${timestamp}.${rawBody}`).digest('base64');
return signatureHeader.split(' ').some((entry) => {
const sig = entry.split(',')[1] ?? entry; // strip "v1,"
try { return crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected)); }
catch { return false; } // length mismatch
});
}
Use the raw body (before JSON parsing). Re-serialized JSON will not match.
For complete handlers with tests, see examples/express/, examples/nextjs/, examples/fastapi/.
Webhook Payload
Fathom sends one webhook type, new meeting content ready, fired once per meeting when the recording finalizes (the same moment the summary email goes out). The body is the Meeting object. There is no event-type field to dispatch on.
| Field | Notes |
|---|---|
title, meeting_title | Recording title; calendar event title (nullable) |
recording_id | Integer ID of the recording |
url, share_url | Links to the recording in Fathom |
created_at, recording_start_time, recording_end_time | ISO 8601 |
recorded_by | { name, email, email_ |
calendar_invitees | [{ name, email, email_ |
shared_with | no_teams, single_team, multiple_teams, all_teams |
default_summary | { template_ if include_summary |
transcript | [{ speaker: { display_ if include_transcript |
action_items | [{ description, completed, assignee, ... }] if include_action_items |
crm_matches | { contacts, companies, deals } if include_crm_matches |
Important Headers
| Header | Description |
|---|---|
webhook-id | Unique message ID; unchanged on retries, so use it for idempotency |
webhook-timestamp | Unix timestamp in seconds |
webhook-signature | v1,<base64> entries, space-delimited |
Environment Variables
FATHOM_WEBHOOK_SECRET=whsec_xxxxx # One secret per webhook, shown when it is created
Local Development
# Start tunnel (no account needed)
npx hookdeck-cli listen 3000 fathom --path /webhooks/fathom
Set the printed URL as the webhook's Destination URL in Fathom (Settings → API Access → Manage → Add Webhook), then use Send test payload or record a short meeting.
Reference Materials
- references/overview.md - What Fathom webhooks are, payload fields, delivery behaviour
- references/setup.md - Create a webhook in Settings or via the API, get the secret
- references/verification.md - Signature verification details, manual Python, gotchas