FastFollow ingests real-time events from every integrated service — calendars, CRMs, transcription providers, and email infrastructure. Outbound webhooks (FastFollow → your endpoints) are on the near-term roadmap.
Third-party services (Google, Resend, HubSpot, etc.) push events to FastFollow. You don't register these directly — FastFollow sets them up automatically when you connect each integration.
Every inbound endpoint verifies a provider-specific signature before processing. Verification failures return HTTP 401 and never touch your data.
Outbound webhooks let your systems subscribe to FastFollow events without polling. The system is in design — the event catalog and security model below are stable, but the subscription API is not yet live.
If outbound webhooks are blocking your project, reach out — we're running a private beta.
Each connected integration pushes events to a dedicated endpoint
/api/webhooks/calendar/api/webhooks/microsoft/api/webhooks/hubspot/api/webhooks/resend/api/webhooks/recall/api/webhooks/fathom/api/webhooks/gong/api/webhooks/slack/api/webhooks/stripeHow FastFollow validates inbound webhooks — and how outbound webhooks will be signed
crypto.timingSafeEqualOutbound (planned) — how you'll verify in your endpoint
import { createHmac, timingSafeEqual } from "crypto";
export function verify(rawBody: string, header: string, secret: string) {
const [tsPart, sigPart] = header.split(",");
const timestamp = tsPart.split("=")[1];
const signature = sigPart.split("=")[1];
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) {
throw new Error("stale_signature");
}
const expected = createHmac("sha256", secret)
.update(`${timestamp}.${rawBody}`)
.digest("hex");
if (!timingSafeEqual(
Buffer.from(expected, "hex"),
Buffer.from(signature, "hex")
)) {
throw new Error("invalid_signature");
}
}Always verify over the raw body — not the parsed JSON. Frameworks like Express body-parser can re-serialize JSON with different whitespace, which breaks HMAC comparison.
Coming in the outbound webhook beta — the names below are stable
meeting.endedA connected meeting (Meet, Zoom, Teams) ended and transcripts are queued.
followup.generatedAn AI-drafted follow-up is ready for human approval.
followup.sentAn approved follow-up was dispatched through Resend.
approval.completedA human approved or rejected a drafted follow-up.
deal.score_changedThe deal intelligence score on an Opportunity Room crossed a threshold.
room.engagementA customer interacted with an Opportunity Room (page view, MAP item completion).
Every inbound webhook handler returns HTTP 200 as quickly as possible, then processes the event asynchronously. We'll do the same on outbound:
Every webhook event carries an X-FastFollow-Event-Id header. Your handler must be idempotent over this ID:
Tunnel a public URL to localhost so providers can reach your dev environment
ngrok
# Forward a public URL to your local server
ngrok http 3000
# Use the https forwarding URL in
# Resend/HubSpot/Stripe webhook config:
# https://abc123.ngrok.io/api/webhooks/resendCloudflare Tunnel
# Stable named tunnels survive restarts
cloudflared tunnel --url http://localhost:3000
# Replays from the provider dashboard
# are essential — never assume first-try delivery
# in production handlers.