Post meeting summaries to Slack
When a summary finishes, verify the webhook signature, fetch the summary, and post it to Slack.
This sends meeting content off your device
Meetily is privacy-first and local by default. This automation reads summary text and sends it to a third party (Slack). You are the data controller for that transfer: get the participants' consent, scope the token to read only, and treat the destination as untrusted. Never hard-code a token in a script you share; read it from the environment or the loopback token file.
This recipe posts a meeting summary to Slack the moment it's ready. It subscribes to the summary.completed webhook event, verifies the HMAC signature, fetches the summary with a scoped token, and posts to a Slack incoming webhook.
First, turn on the Automation API and webhook delivery under Settings > Integrations - webhook delivery is off by default, and the webhook routes are gated on it (see Enable & connect).
1. Register the webhook
Register on summary.completed. Webhooks can't be delivered to a loopback or private address unless you've explicitly added that host:port to Local webhook targets, so for Slack run a tunnel (ngrok, cloudflared) in front of your receiver and register the tunnel's public HTTPS URL. See Webhooks & SSE for the full registration, SSRF, and HMAC details.
curl -s -X POST http://127.0.0.1:8420/v1/webhooks \
-H "Authorization: Bearer $MEETILY_PRO_TOKEN" \
-H "content-type: application/json" \
-d '{"url":"https://YOUR-TUNNEL.example/hook","events":["summary.completed"]}'The 201 response carries an hmac_secret shown only once - store it immediately. There's no endpoint to reveal it again.
A new webhook is `pending` and delivers nothing until you approve it
Registering a destination does not start delivery. It lands in approval_state: pending and sends nothing - silently, with no failed-delivery log entry - until you approve it under Settings > Integrations > Destinations, which moves it to allowed. If your webhook seems dead, check its approval_state with GET /v1/webhooks/{id} before debugging your receiver.
2. Receive, verify, fetch, post
Standard-library Python only - no SDK. Verify the signature over {timestamp}.{body}, then fetch the summary and post it:
import hmac, hashlib, json, urllib.request
HMAC_SECRET = "whsec_..." # returned once at registration
SLACK_WEBHOOK = "https://hooks.slack.com/services/XXX"
MEETILY = "http://127.0.0.1:8420"
TOKEN = "..." # a read-scoped token, from env in real code
def verify(secret, timestamp, raw_body, header_sig):
mac = hmac.new(secret.encode(), f"{timestamp}.{raw_body}".encode(), hashlib.sha256).hexdigest()
return hmac.compare_digest(f"sha256={mac}", header_sig)
def handle(headers, raw_body):
ts = headers["X-Meetily-Timestamp"]
sig = headers["X-Meetily-Signature"]
if not verify(HMAC_SECRET, ts, raw_body, sig):
return # reject unsigned or tampered deliveries
event = json.loads(raw_body)
if event["event"] != "summary.completed":
return
meeting_id = event["resource"]["id"] # the resource id for this event is the meeting id
# Fetch the actual content with your own token - the webhook payload never carries it.
req = urllib.request.Request(
f"{MEETILY}/v1/meetings/{meeting_id}/summary",
headers={"Authorization": f"Bearer {TOKEN}"},
)
summary = json.loads(urllib.request.urlopen(req).read())
text = json.dumps(summary.get("result", summary))[:3000]
urllib.request.urlopen(urllib.request.Request(
SLACK_WEBHOOK,
data=json.dumps({"text": f"Summary for {meeting_id}:\n{text}"}).encode(),
headers={"content-type": "application/json"},
))Make your handler idempotent, keyed on event_id
Delivery is at-least-once by default, so the same event can arrive more than once. Treat a repeat event_id as a no-op, not a second post. Always compare the signature with hmac.compare_digest, never ==.
Troubleshooting
- Nothing arrives. Check
approval_state(must beallowed) and that webhook delivery is enabled in Settings. Both fail silently. - Inspect attempts.
GET /v1/webhooks/{id}/deliverieslists each attempt with a reason code. - Test end to end.
POST /v1/webhooks/{id}/testsends a synthetic delivery so you can confirm your receiver and signature check work before a real summary fires.
The exact resource shape per event, the full 17-event catalogue, and delivery retry mechanics are in the Event catalogue and Webhooks & SSE.
Last updated on
