Gareth Wilson Gareth Wilson

Guide to Circleback Webhooks: Features and Best Practices

Published


Circleback webhooks send your meeting data out of Circleback once a meeting has been processed: the notes, action items, transcript and insights that Circleback's AI produces. If your team records meetings with Circleback, a webhook is how those outcomes reach a CRM, a project tracker, a knowledge base or your own product.

This guide covers how Circleback webhooks are set up and signed, what each request contains, and the practices that keep a Circleback receiver reliable.

What are Circleback webhooks?

In Circleback, a webhook is a step in an automation. The automation's conditions decide which meetings it runs after, and its Send webhook request step names the endpoint and the meeting outcomes to include. Each matching meeting becomes one POST with a JSON body describing the meeting.

There are no event types. Every request is the same kind of thing, a meeting, and the body has no field that names an event. Which fields are filled depends on the outcomes you chose in the step.

Each request carries an x-signature header: the bare hex HMAC-SHA256 of the raw body, keyed with the signing secret Circleback gives you for that automation step.

Circleback webhook features

FeatureDetails
ConfigurationAutomations > New automation, with a Send webhook request step
FilteringThe automation's conditions decide which meetings are sent
ContentThe meeting outcomes you select in the step
Event typeNone. Each request is one meeting
Signature headerx-signature
SchemeHMAC-SHA256, hex digest, no prefix
Signed contentThe raw request body only
SecretOne per automation webhook step
TestingA test request for the most recent meeting, sent from the step
BackfillSelect past meetings and run the automation from the Actions menu
RetriesNot documented
Source IPsNot published

What the payload contains

Every request is a meeting object:

FieldContents
idThe Circleback meeting ID. https://circleback.ai/meetings/${id} links to it
name, createdAt, durationThe meeting's name, creation time (ISO string) and length in seconds
urlThe video call link, or null
recordingUrlThe recording file, valid for 24 hours, and only present if saving recordings is turned on
tags, icalUidTag names, and the calendar event's ID or null
attendeesname and email for each attendee, either of which can be null
notesThe meeting notes in Markdown
actionItemsid, title, description, assignee (or null) and status (PENDING or DONE)
transcriptSegments with speaker, text and timestamp in seconds
insightsAn object keyed by insight name, each an array of insight, speaker and timestamp

A trimmed version of Circleback's example:

{
  "id": "WRweb12iCBimU6Vo8cD7z",
  "name": "Event Venue Review",
  "createdAt": "2023-07-25T20:30:57.926Z",
  "duration": 1306.09,
  "url": "https://meet.google.com/abc-defgh-xyz",
  "recordingUrl": null,
  "tags": ["Events"],
  "icalUid": "1a2b3c@google.com",
  "attendees": [
    { "name": "John Appleseed", "email": "john@example.com" }
  ],
  "actionItems": [
    {
      "id": 253,
      "title": "Review and finalize venue options",
      "description": "Review pricing and availability of venues and pick a venue for the event.",
      "assignee": null,
      "status": "PENDING"
    }
  ],
  "transcript": [
    { "speaker": "John Appleseed", "text": "Hey, how's it going?", "timestamp": 4.56 }
  ]
}

An insight is a string, or an object when the insight has custom fields, so check its type before using it.

Setting up Circleback webhooks

  1. In Circleback, open Automations and select New automation.
  2. Add conditions that limit which meetings the automation runs after, then select Next.
  3. Select Send webhook request.
  4. Enter the endpoint URL and choose the meeting outcomes to include.
  5. Copy the signing secret and store it server-side, for example as CIRCLEBACK_WEBHOOK_SECRET.
  6. Optionally, send a test request for the most recent meeting.
  7. Select Done, name the automation and Save.

Each automation step has its own secret. If you run several automations, give each one its own endpoint or its own Hookdeck source, so every receiver checks requests against the right secret.

To send meetings that happened before you set up the automation, select them in Circleback's meeting list and choose the automation from the Actions menu.

Securing Circleback webhooks

Compute an HMAC-SHA256 of the raw body with the signing secret, hex-encode it, and compare it with x-signature in constant time. Circleback calls this step optional, but it is the only way to tell that a request came from Circleback.

const crypto = require('crypto');
const express = require('express');

function verifyCirclebackSignature(rawBody, header, secret) {
  if (typeof header !== 'string' || !secret) return false;
  const expected = Buffer.from(
    crypto.createHmac('sha256', secret).update(rawBody).digest('hex'),
    'utf8'
  );
  const received = Buffer.from(header.trim().toLowerCase(), 'utf8');
  return received.length === expected.length && crypto.timingSafeEqual(received, expected);
}

const app = express();

app.post('/webhooks/circleback', express.raw({ type: '*/*' }), (req, res) => {
  const secret = process.env.CIRCLEBACK_WEBHOOK_SECRET;
  if (!secret) return res.sendStatus(500); // fail closed

  if (!verifyCirclebackSignature(req.body, req.get('x-signature'), secret)) {
    return res.sendStatus(401);
  }

  const meeting = JSON.parse(req.body.toString('utf8'));
  // Upsert on meeting.id, copy the recording if you need it, then process asynchronously.
  res.sendStatus(200);
});

The same check in Python:

import hashlib
import hmac


def verify_circleback_signature(raw_body: bytes, header, secret: str) -> bool:
    if not header or not secret:
        return False
    expected = hmac.new(secret.encode("utf-8"), raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(header.strip().lower().encode("utf-8"), expected.encode("utf-8"))

Circleback's own sample mounts express.raw({ type: 'application/json' }). Using */* keeps the body raw whatever content type arrives.

Make Circleback webhooks production-ready. Hookdeck Event Gateway verifies the x-signature header, stores every meeting export, and delivers it to your services with retries and replay you control.

Circleback webhook limitations and pain points

No documented retries

The Problem: A meeting sent while your endpoint is down may never arrive.

Why It Happens: Circleback documents no timeout, no success code and no retry policy, so you can't count on a failed request being sent again.

Workarounds:

  • Keep the endpoint highly available and return 200 quickly.
  • After an outage, select the affected meetings and run the automation again from the Actions menu.

How Hookdeck Can Help: Hookdeck accepts and stores each request as it arrives, then delivers it to your service with automatic retries, so your own downtime delays meetings instead of losing them.

The Problem: The recording can't be downloaded when you get round to processing the meeting.

Why It Happens: recordingUrl is valid for 24 hours. A queue backlog, a retry or a replay of an older request can carry a link that has already expired.

Workarounds:

  • Copy the recording to your own storage soon after the request arrives.
  • Treat a failed download as expected for older requests, not as an error to retry forever.

How Hookdeck Can Help: Hookdeck delivers each request as soon as your service can take it, and issues tell you when deliveries are failing so a backlog doesn't build up unnoticed.

No event type and no timestamp

The Problem: You can't tell a first export from a repeat, and a captured request still verifies if sent again.

Why It Happens: The body is the meeting and nothing else. Only the body is signed, and no timestamp or delivery ID is sent. Re-running an automation on past meetings sends them again.

Workarounds:

  • Upsert on the meeting id, so a repeat updates rather than duplicates.
  • Keep the endpoint on HTTPS.

How Hookdeck Can Help: Hookdeck's deduplication can drop repeated requests with the same meeting id.

Best practices

Verify against the raw body

The signature covers the exact bytes Circleback sent. Use express.raw() in Express, await request.text() in a Next.js route handler and await request.body() in FastAPI, and parse only after the check passes.

Include only the outcomes you use

Transcripts make requests large. If you only need notes and action items, leave the transcript out of the step.

Guard against nulls

url, recordingUrl, icalUid, attendee names and emails, and action item assignees can all be null. Use optional access throughout.

Handle sensitive data carefully

Transcripts and notes can contain anything said in a meeting. Keep the endpoint on HTTPS and restrict who can read stored requests.

Acknowledge fast and process asynchronously

Verify, store the meeting, return 200, and do the work afterwards. See why to process webhooks asynchronously and our guide to webhook idempotency.

Conclusion

Circleback sends one signed POST per meeting from an automation step, with an x-signature header holding the bare hex HMAC-SHA256 of the raw body. Verify it with that step's secret, upsert on the meeting id, copy recordings within 24 hours, and plan for missed requests, because Circleback documents no retries.

Hookdeck Event Gateway sits in front of your receiver, checks every Circleback signature, and holds each meeting until your service has processed it.

Get started with Hookdeck for free and handle Circleback 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.