Cal.com BOOKING_CREATED webhook to a Sume video run, verified
Cal.com signs webhooks with x-cal-signature-256. Verify it, turn BOOKING_CREATED into a Sume Format run, and keep the Idempotency-Key stable on retries.

To start a Sume Format run when someone books a meeting in Cal.com, subscribe a webhook to BOOKING_CREATED, verify the x-cal-signature-256 header against the raw body, and call POST /v1/formats/{handle}/{slug}/runs with an Idempotency-Key built from the booking. The create call returns a 202 receipt, so your receiver can answer Cal.com straight away.
Cal.com and Sume both sign with HMAC SHA256, but the header names and the signed string differ, so you need two small verifiers, not one.
What Cal.com documents
Cal.com's webhooks guide lists triggers including BOOKING_CREATED, BOOKING_CANCELLED, MEETING_ENDED, RECORDING_READY, RECORDING_TRANSCRIPTION_GENERATED and FORM_SUBMITTED (read 2026-10-10). It says the x-cal-signature-256 header carries an HMAC SHA256 signature, and that the x-cal-webhook-version header versions the payload.
Most payloads are wrapped as {triggerEvent, createdAt, payload}. MEETING_STARTED and MEETING_ENDED are flat, and the page says they do not support custom payload templates. Pin the version header in your receiver and log it, so a payload change shows up as a rejected version instead of a silent mapping bug.
| Topic | Cal.com | Sume |
|---|---|---|
| Signature header | x-cal-signature-256 | x-sume-webhook-signature: sume-v1=<hex> |
| Signed string | See the Cal.com page for the exact input | timestamp.raw_body with HMAC SHA256 |
| Version signal | x-cal-webhook-version | Event name format.run.terminal plus outcome |
| Envelope | triggerEvent, createdAt, payload for most events | Full run receipt |
| Replay guard | Not covered here | Timestamp header, five-minute tolerance |
Booking to run
Use the booking identifier from the payload plus the trigger name as the key, for example booking-<uid>-created. Cal.com sends no Sume header, so the key is yours to define, and it stays the same across redeliveries. A repeat with the same key and body returns 200 with idempotency_hit: true. The same key with a different body returns 409 idempotency_conflict, which usually means a rescheduled booking changed a field you put in input.
Put attendee details and the meeting topic into input, which is caller data, at most 64 top-level keys and 2 MiB, and never echoed in output. Keep your decisions in instruction, such as a short welcome clip in the host's tone. Add generation_spend_cap_usd so one booking cannot spend more than you plan; the platform maximum is $500.
Use RECORDING_READY separately
RECORDING_READY is a second trigger on its own timeline, so treat it as a second run with its own key such as booking-<uid>-recording. Pass the recording link as a public HTTPS attachment URL. Attachments share one budget of 30, at most 30 images, 10 videos and 10 audio files. A recap clip built from the recording and a transcript is a natural second Format, but it belongs to a different slug than the welcome clip.
Close the loop
Set communication.webhook_url on the run to your own route and verify the format.run.terminal event with the secret from GET /v1/webhooks/signing-secret. Refuse an empty secret in code, so a missing environment variable fails loudly rather than accepting everything. Branch on outcome: ok, degraded or error.
Cancelled and skipped runs never deliver, so poll status_url for any run that has no event after its expires_at. That is 90 minutes after creation, or earlier if the run goes silent. If Cal.com delivery fails on your side, return a non-2xx only before you have stored the booking, because the run create is already safe to repeat.
Failure cases to plan for
Three failures recur in this pattern. First, a cancelled booking arrives after the welcome run was created; call the run's cancel_url if it is still queued or processing, and accept that a finished clip simply goes unused. Second, a rescheduled booking changes the start time, so decide whether the key should include it. Third, a Cal.com custom payload template can change field names, so pin the template in version control and read fields defensively.
Log the Cal.com delivery, the Sume receipt id and the final outcome together under one booking identifier. When a host asks why a guest never got a clip, that single line answers it without digging through two dashboards. Do not log the raw signature header or the signing secret.
Sources
Related posts
More in Integrations
- Docker Agent YAML: add Sume as a remote MCP toolset
Docker Agent takes a remote MCP URL, headers and a tools allowlist. Here is the Sume entry with a Bearer key from the environment and a read-only tool list.
- Freshdesk Trigger Webhook: 1000 calls an hour and Sume bulk runs
Freshdesk automations cap webhook calls at 1000 an hour and retry failures every 30 minutes. Here is how a relay maps ticket bursts onto Sume bulk runs.
- Grafana alert webhook with HMAC to a Sume run: incident explainer
Grafana's webhook contact point can sign alerts with HMAC over timestamp:body. Verify it, then start a Sume Format run per firing alert with a stable key.
- Jotform webhook rawRequest and a 30 s timeout: start a Sume run
Jotform posts submissions as form data with a rawRequest field and a 30 s timeout. Answer fast, start a Sume Format run, and let a webhook return the result.
Written by Sume