Gareth Wilson Gareth Wilson

Guide to MeetGeek Webhooks: Features and Best Practices

Published


MeetGeek is an AI meeting assistant: it joins or records your Zoom, Google Meet and Teams calls, then produces a transcript, summary, highlights and action items. Analysis takes a while after the meeting ends, and MeetGeek's webhook is the signal that it's done, so your CRM, project tracker or knowledge base can pull the results through MeetGeek's Public API without polling.

This guide covers the single notification MeetGeek sends, how it's tied to individual users, verifying X-MG-Signature, and the gaps you'll need to work around.

What are MeetGeek webhooks?

MeetGeek has one webhook, and it's per user: each person sets a single URL in the Public API section of their Integrations page. When analysis of one of their meetings finishes, MeetGeek sends a JSON POST to that URL.

The body is minimal. A successful analysis sends a message and the meeting_id; a failed one sends only a message. Everything else (transcript, summary, highlights) comes from the Public API, using the meeting_id.

Requests carry X-MG-Signature, a hex HMAC-SHA256 of the raw body, keyed with the secret configured for the Public API.

MeetGeek webhook features

FeatureDetails
ConfigurationIntegrations > Public API, one URL per user
TriggerMeeting analysis finished (success or failure)
Signaturehex HMAC-SHA256
Signature headerx-mg-signature
Signed contentThe raw request body
Key"The configured secret" for the Public API (location undocumented)
BodyJSON: message, plus meeting_id on success
Event routingNone; branch on meeting_id
Acknowledgement200 OK, no body needed
RetriesUp to 2 (3 POSTs in total)

Events and payloads

EventBodyUse cases
successful-analysis{"message": "File analyzed successfully", "meeting_id": "9433976b-cfa3-4373-9afb-eb0b7a5915df"}Fetch transcript, summary and highlights via the Public API
failed-analysis{"message": "File analyzed failed"}Alert, or retry the upload

successful-analysis and failed-analysis are the docs' section headings, used as sample file names; they aren't values sent on the wire. The message strings are human-readable text, so test for meeting_id rather than matching the wording.

Published payload example

The failure form, from the webhook samples library, shows how little it carries: no meeting ID, user or time.

{
  "message": "File analyzed failed"
}

Setting up MeetGeek webhooks

Prerequisites

  • A MeetGeek account with access to the Public API
  • A public HTTPS endpoint that accepts POST

Register Your Endpoint

  1. Open the Integrations page in MeetGeek and go to the Public API section.
  2. Enter your webhook URL and save. Each user has one URL.
  3. Have each team member whose meetings you need do the same, or rely on team sharing (see below).

Get Your Webhook Secret

Paste the webhook secret configured for the MeetGeek Public API. Deliveries without a signature fail verification.

MeetGeek's docs call the key "the configured secret" without saying where it's set or shown; look in the same Public API section as the webhook URL. Store it as WEBHOOK_SECRET and use it as UTF-8 bytes, unmodified.

Test a delivery

Start a local receiver and forward requests with the Hookdeck CLI:

npx hookdeck-cli listen 3000 meetgeek --path /webhooks/meetgeek

Set the CLI's URL as your webhook, record a short test meeting, and wait for analysis to finish. Then call the Public API with the meeting_id you receive.

Securing MeetGeek webhooks

Compute HMAC-SHA256 over the raw body with the secret's UTF-8 bytes, hex-encode it, and compare it with X-MG-Signature in constant time. MeetGeek's webhook appendix has samples in Python, Go, Node and Java.

const crypto = require('node:crypto');

function verifySignature(rawBody, headers, secret) {
  if (!Buffer.isBuffer(rawBody) || typeof secret !== 'string' || !secret) return false;
  const signature = headers['x-mg-signature'];
  if (typeof signature !== 'string') return false;
  const key = Buffer.from(secret, 'utf8');
  const message = rawBody;
  const candidates = [signature];
  const expected = crypto.createHmac('sha256', key).update(message).digest();
  return candidates.some((candidate) => {
    if (!/^[0-9a-fA-F]{64}$/.test(candidate)) return false;
    const received = Buffer.from(candidate, 'hex');
    return received.length === expected.length && crypto.timingSafeEqual(received, expected);
  });
}

The handler acknowledges with a plain 200, ignores a meeting_id it has already queued, and flags failures for follow-up.

const express = require('express');

function createMeetGeekApp({ queueMeetingFetch, alreadyQueued, reportFailure }) {
  const app = express();
  app.post('/webhooks/meetgeek', express.raw({ type: '*/*' }), async (req, res) => {
    const secret = process.env.WEBHOOK_SECRET;
    if (!secret) return res.sendStatus(500);
    if (!verifySignature(req.body, req.headers, secret)) return res.sendStatus(401);
    let parsed;
    try {
      parsed = JSON.parse(req.body.toString('utf8'));
    } catch {
      return res.sendStatus(400);
    }
    if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) return res.sendStatus(400);
    const { meeting_id, message } = parsed;
    if (!meeting_id && !message) return res.sendStatus(400);
    try {
      if (meeting_id) {
        if (!(await alreadyQueued(meeting_id))) await queueMeetingFetch(meeting_id);
      } else {
        await reportFailure(message);
      }
    } catch {
      return res.sendStatus(503);
    }
    return res.sendStatus(200);
  });
  return app;
}

The signature covers only the body, and the success body for a given meeting never changes, so a replay verifies indefinitely. Deduplicating on meeting_id is enough to make that harmless.

Hookdeck's MeetGeek source type verifies X-MG-Signature over the raw body. MeetGeek gets 200 every time, which also stops it retrying; a failed check is recorded as failed verification and the request isn't passed on. There's no timestamp, and so no tolerance to apply.

Make MeetGeek webhooks production-ready. Hookdeck Event Gateway collects every user's MeetGeek webhooks on one verified source, removes duplicate meeting_id deliveries, and keeps them replayable beyond MeetGeek's two retries.

MeetGeek webhook limitations and pain points

Failures don't say which meeting

The Problem: You know an analysis failed, but not which meeting or whose.

Why It Happens: The failure body is only {"message": "File analyzed failed"}.

Workarounds:

  • Track meetings you expect to be analysed and look for ones that never produce a success webhook.
  • Use separate URLs per user (for example a path segment) so at least the user is known.

How Hookdeck Can Help: Hookdeck's request log records when each failure arrived and on which source, which helps you match it to a recording.

One URL per user

The Problem: Collecting every meeting in an organisation means configuring the webhook for each user.

Why It Happens: The webhook is set on each user's Integrations page, with no organisation-level setting documented.

Workarounds:

  • Have each user point at the same receiver, with a user identifier in the path.
  • Use team sharing so meetings reach a user who has the webhook set.

How Hookdeck Can Help: One Hookdeck source URL can be given to every user, so all deliveries land in one place with one secret check.

Duplicates from team sharing and retries

The Problem: The same meeting is processed several times.

Why It Happens: For a team-shared meeting, every member with view access gets the webhook, and unacknowledged requests are retried up to twice.

Workarounds:

  • Deduplicate on meeting_id before fetching from the API.

How Hookdeck Can Help: Hookdeck deduplication on meeting_id drops repeats before they reach your service.

Short, unspecified retry window

The Problem: A brief outage can lose the notification for good.

Why It Happens: MeetGeek sends at most three requests and documents neither the spacing nor the timeout.

Workarounds:

  • Periodically list recent meetings through the Public API to catch any you missed.

How Hookdeck Can Help: Hookdeck accepts the first request and holds it until your service is ready, retrying on a schedule you set.

Undocumented secret location

The Problem: It's unclear where the signing key comes from or how to rotate it.

Why It Happens: The docs refer to "the configured secret" only.

Workarounds:

  • Check the Public API section of the Integrations page, and ask MeetGeek support if it isn't there.
  • Test with a real delivery before enforcing verification in production.

How Hookdeck Can Help: Failed verifications are visible in Hookdeck, so a wrong or rotated secret shows up straight away.

Best practices

Answer with a bare 200

MeetGeek retries anything that isn't acknowledged with 200 OK; no body is needed. Return it as soon as the notification is stored.

Fetch results in the background

The webhook only says analysis is ready. Calling the Public API for the transcript and summary takes time, so do it in a worker, as described in our asynchronous processing guide.

Key everything on meeting_id

It's the only identifier in the payload. Store it with whatever you create from the meeting, following the idempotency guide.

Protect meeting content

Transcripts and summaries fetched after the webhook can contain sensitive discussion. Apply the same access controls and retention to them as to the original recordings.

Conclusion

MeetGeek's webhook does one job, telling you a meeting's analysis is ready, and the HMAC signature on it is easy to check. Its limits are the per-user setup, a failure body with no meeting ID, duplicate deliveries for shared meetings and only two retries, so pair it with meeting_id deduplication and a periodic API sweep.

Hookdeck Event Gateway brings every user's MeetGeek notifications into one verified, deduplicated and replayable stream.

Get started with Hookdeck for free and handle MeetGeek webhooks reliably in minutes.


Gareth Wilson

Gareth Wilson

Product Marketing

Multi-time founding marketer, Gareth is PMM at Hookdeck and author of the newsletter, Community Inc.