Skip to Content
IntegrationsWebhooks

Webhooks

Pro+ adds signed HTTPS webhooks so your own systems can react the moment a meeting or D&D session is ready—without polling DiscMeet.

Typical uses:

  • Zapier / Make — Start a workflow when a transcript finishes (Slack, Notion, CRM, email, databases).
  • Custom backends — Enqueue jobs, update an internal app, or sync metadata to your data warehouse.

Webhooks are per Discord server (guild). Anyone who can manage this server in the DiscMeet dashboard can configure the webhook URL and signing secret in Integrations—the same rules as the rest of server settings: you need Manage Channels, Administrator, or to be the Discord server owner for that guild (see the Integrations page if you don’t have access).


What you need

  1. An active Pro+ subscription on the guild owner’s DiscMeet account (the account that owns billing for that server).
  2. A public HTTPS URL that accepts POST requests with a JSON body (Zapier “Catch Hook”, Make “Webhooks” custom hook, or your own server).
  3. (Recommended) A signing secret so you can verify requests really came from DiscMeet.

Configure in DiscMeet

  1. Sign in and open the dashboard .
  2. Select the server you want.
  3. In the sidebar, open Integrations.
  4. Paste your webhook URL (must start with https://).
  5. Click Rotate secret (or equivalent) once, copy the secret immediately, and store it somewhere safe. DiscMeet only shows the full secret at creation time; later you’ll only see the last four characters.
  6. Save the URL.

If Pro+ is not active for that server’s owner, the Integrations screen will prompt you to upgrade.


Events

For each recording, transcript.ready fires when notes are ready. audio.ready fires only when MP3 recording is turned on for that server in dashboard  → Settings—that is what creates the full downloadable file. If MP3 recording is off, you will not get audio.ready for new meetings, but transcript.ready still works as usual.

When an event is sent, it includes the same meeting_id, plus the channel name and participant list, so you can match transcript and audio and label automations clearly.

transcript.ready

Fired when transcription has finished for a regular meeting or a D&D session. Each payload includes where the session lives in Discord, who spoke, and the notes and transcript text (plain strings—escape newlines and quotes as usual):

  • discord_channel_name — The name of the Discord text channel DiscMeet ties to this meeting (where notes would be posted). null only if the name could not be looked up at send time (for example, a brief Discord API issue).
  • participant_namesDisplay names of people who spoke, in order of first appearance. JSON array of strings; use [] when no speakers were detected.
  • notes — A summary of the conversation generated from the transcript. Supports markdown formatting. "" if there is nothing to send.
  • transcript — The conversation text with speaker + timestamp lines (who said what, and when). Supports markdown formatting. "" if there is nothing to send.
  • audio_url — HTTPS URL for the merged full-session MP3 (stable path on DiscMeet’s recording host). The file exists only after merged audio is available (MP3 recording must be on for the server); until then the URL may not download successfully.
{ "event": "transcript.ready", "meeting_id": "550e8400-e29b-41d4-a716-446655440000", "guild_discord_id": "987654321098765432", "recording_type": "meeting", "discord_channel_name": "meeting-transcripts", "participant_names": ["Alex", "Jamie"], "notes": "## Meeting — Mar 28, 2026\n\n**Alex** (00:01): Quick sync on the roadmap.\n\n**Jamie** (00:45): Sounds good.", "transcript": "## Meeting — Mar 28, 2026\n\n**Alex** (00:01): Quick sync on the roadmap.\n\n**Jamie** (00:45): Sounds good.", "audio_url": "https://rails.discmeet.com/recordings/550e8400-e29b-41d4-a716-446655440000/audio.mp3", "occurred_at": "2026-03-28T12:34:56Z" }
{ "event": "transcript.ready", "meeting_id": "6ba7b810-9dad-11d1-80b4-00c04fd430c8", "guild_discord_id": "987654321098765432", "recording_type": "session", "discord_channel_name": "the-broken-seal", "participant_names": ["DM", "Asha", "Rook"], "notes": "## D&D Session — The Broken Seal\n\n**DM** (00:02): You enter the hall...", "transcript": "## D&D Session — The Broken Seal\n\n**DM** (00:02): You enter the hall...", "audio_url": "https://rails.discmeet.com/recordings/6ba7b810-9dad-11d1-80b4-00c04fd430c8/audio.mp3", "occurred_at": "2026-03-28T12:35:10Z" }
FieldTypeMeaning
eventstringAlways transcript.ready for this event.
meeting_idstring (UUID)Stable public id for this recording. Use it to correlate with audio.ready and your own databases.
guild_discord_idstringDiscord snowflake of the server.
recording_typestring"meeting" or "session" (D&D).
discord_channel_namestring or nullName of the Discord text channel for this meeting’s notes.
participant_namesarray of stringsWho spoke, first-seen order; empty array if unknown.
notesstringConversation summary notes generated from the transcript. Markdown-friendly text string.
transcriptstringSpeaker + timestamp transcript (who said what, and when). Markdown-friendly text string.
audio_urlstringHTTPS URL for the merged MP3 (…/recordings/{meeting_id}/audio.mp3). File is available only after merged audio exists (MP3 recording on).
occurred_atstringISO 8601 timestamp in UTC when the event was emitted.

notes vs transcript: both are plain strings in the webhook. Use transcript when you need the timestamped speaker-by-speaker conversation. Use notes when you want a concise summary of the conversation based on that transcript.

You can send notes or transcript straight into Notion, Google Docs, email bodies, or your database, and use discord_channel_name and participant_names to file or filter rows. Webhooks give you downstream copies without scraping Discord.

When MP3 recording is on, you might receive transcript.ready before or after audio.ready depending on whether the MP3 finishes before or after transcription. Always use meeting_id to match the two.

audio.ready

Sent only when MP3 recording is enabled for the server (see dashboard  → Settings → MP3 recording). DiscMeet waits until transcription is finished and a full-session MP3 link exists. If MP3 recording is off, or there is no audio file to share, this event is not sent.

The same discord_channel_name and participant_names fields appear here as in transcript.ready, so you can label downloads or automations without waiting for the transcript event.

{ "event": "audio.ready", "meeting_id": "550e8400-e29b-41d4-a716-446655440000", "guild_discord_id": "987654321098765432", "recording_type": "meeting", "discord_channel_name": "meeting-transcripts", "participant_names": ["Alex", "Jamie"], "audio_url": "https://rails.discmeet.com/recordings/550e8400-e29b-41d4-a716-446655440000/audio.mp3", "occurred_at": "2026-03-28T12:35:02Z" }
FieldTypeMeaning
eventstringAlways audio.ready.
meeting_idstring (UUID)Same id as in transcript.ready for that recording.
guild_discord_idstringDiscord server snowflake.
recording_typestring"meeting" or "session".
discord_channel_namestring or nullSame meaning as in transcript.ready.
participant_namesarray of stringsSame meaning as in transcript.ready.
audio_urlstringHTTPS URL to the merged MP3—usually the same stable public path as transcript.ready (…/recordings/{meeting_id}/audio.mp3). If that is not available, a time-limited presigned URL; download presigned links promptly before they expire.
occurred_atstringISO 8601 UTC timestamp.

How requests are sent

ItemValue
MethodPOST
URLThe HTTPS URL you configured
Content-Typeapplication/json
User-AgentDiscMeet-Webhooks/1.0
BodyUTF-8 JSON object (see Events)
X-Discmeet-SignaturePresent when a secret is configured — see Verifying signatures

Timeouts and retries:

  • Each attempt uses a 15 second HTTP timeout.
  • If the call fails with a retryable error (network failure, HTTP 429, or 5xx), DiscMeet schedules up to 5 retries, 30 minutes apart.
  • 4xx responses (except 429) are treated as non-retryable: the payload is not retried automatically.

transcript.ready bodies can be large—both notes and transcript are strings and may contain long markdown or other text. Ensure your endpoint, Zapier/Make limits, and timeouts can handle that.


Zapier (first-time friendly)

  1. Create a Zap. Trigger: Webhooks by ZapierCatch Hook.
  2. Zapier shows you a unique HTTPS URL. Copy it.
  3. In DiscMeet, open the dashboard Integrations, paste that URL as the webhook URL, and save.
  4. Run a real meeting (or wait for the next one). Zapier’s test screen should show a POST with JSON body.
  5. Map fields like event, meeting_id, guild_discord_id, recording_type, discord_channel_name, participant_names, notes, transcript, audio_url on transcript.ready, and audio_url again on audio.ready if you use both events.

Tips:

  • Use a Filter (or Paths) so you only continue when event equals transcript.ready or audio.ready.
  • If audio.ready never appears, check that MP3 recording is on in dashboard Settings for that server.
  • A follow-up step might GET audio_url to download the MP3. Stable public URLs do not expire like presigned links; if the payload uses a presigned URL, fetch it before expiry.
  • Signature verification in Zapier is limited; many teams filter on guild_discord_id and keep the hook URL private. For stricter checks, point the webhook at your API, verify the signature there, then forward to Zapier.

Make (Integromat)

  1. Create a scenario. Add WebhooksCustom webhook (or Custom trigger).
  2. Create a new hook and copy the HTTPS address.
  3. Paste it into DiscMeet Integrations (from the dashboard ) and save.
  4. Run a meeting; Make receives the JSON payload and you can map each property to later modules (Google Sheets, Slack, HTTP, etc.).

Same guidance as Zapier for filters on event. Treat audio_url as stable when it matches the …/recordings/{meeting_id}/audio.mp3 pattern; otherwise download presigned URLs promptly. Remember audio.ready only runs when MP3 recording is enabled for the server.


Verifying signatures

When a signing secret is set, DiscMeet sends:

X-Discmeet-Signature: sha256=<lowercase_hex>

The HMAC uses SHA-256, the raw JSON body bytes exactly as sent (the same string DiscMeet POSTs—not pretty-printed, not re-serialized), and your shared secret.

Algorithm (conceptually):

expected_hex = HMAC_SHA256(secret, raw_request_body).hexdigest() header_value = "sha256=" + expected_hex

Checklist:

  1. Read the raw body as bytes/string before parsing JSON.
  2. Compute HMAC-SHA256 with your stored secret.
  3. Compare to the header value after the sha256= prefix, using a constant-time string compare if possible.

If the secret is not configured, the header is omitted (webhooks still deliver). That is easier for quick Zapier tests but not recommended for production.

For HMAC snippets in several languages, see Signature verification examples below.


Signature verification examples

rawBody must be the exact bytes of the POST body (UTF-8). In some frameworks that is a Buffer, bytes, []byte, or byte[] before JSON parsing.

import crypto from 'crypto'; function verifyDiscmeetWebhook(rawBody, header, secret) { if (!header || !header.startsWith('sha256=') || !secret) return false; const theirs = header.slice('sha256='.length); const hmac = crypto.createHmac('sha256', secret).update(rawBody, 'utf8').digest('hex'); return crypto.timingSafeEqual(Buffer.from(theirs, 'utf8'), Buffer.from(hmac, 'utf8')); }

Why use webhooks

  • Push — You get your notes automatically as soon as it’s ready.
  • Easy matchingmeeting_id lets you pair transcript.ready and audio.ready for the same recording (when you use MP3 recording).
  • Rich payload — Events include notes, transcript, the Discord channel name, and who spoke, so you can automate recaps, full records, and tidy routing.
  • Optional security — Turn on signature verification with HMAC if you want stricter validation in production.

Last updated on