# Circleback Webhooks

Circleback is an AI meeting notetaker. A **Send webhook request** step in a
Circleback automation POSTs each matching meeting (notes, action items,
attendees, and optionally transcript and insights) as JSON to your endpoint.

## When to Use This Skill

* How do I receive Circleback webhooks after a meeting?
* How do I verify the Circleback `x-signature` header?
* How do I get Circleback meeting notes, action items or transcript via webhook?
* Why is my Circleback webhook signature verification failing?
* How do I export past Circleback meetings to my own endpoint?

## Verification (core)

Circleback sends `x-signature`: the **bare lowercase hex** HMAC-SHA256 of the
**raw request body**, keyed with the signing secret shown in the automation's
webhook step (used as a UTF-8 string). There is no timestamp and no prefix.
Check the header is exactly 64 hex characters *before* decoding (`Buffer.from(x, 'hex')`
silently truncates invalid hex), then compare in constant time:

```javascript
const crypto = require('crypto');

function verifyCirclebackSignature(rawBody, signature, secret) {
  if (typeof signature !== 'string' || !/^[0-9a-f]{64}$/i.test(signature)) return false;
  const expected = crypto.createHmac('sha256', secret).update(rawBody).digest();
  return crypto.timingSafeEqual(expected, Buffer.from(signature, 'hex'));
}

```

Python (`hmac.compare_digest` on bytes, so a non-ASCII header gives 401, not 500):

```python
import hashlib, hmac, re

def verify_circleback_signature(raw_body: bytes, signature: str | None, secret: str) -> bool:
    if not signature or not re.fullmatch(r"[0-9a-fA-F]{64}", signature):
        return False
    expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest().encode()
    return hmac.compare_digest(expected, signature.lower().encode())

```

Read the **raw body** (`express.raw({ type: '*/*' })`, `request.text()`, `await request.body()`),
not re-serialized JSON. Respond `401` on a bad signature.

> **For complete handlers with tests**, see [examples/express/](https://github.com/hookdeck/webhook-skills/tree/main/skills/circleback-webhooks/examples/express/), [examples/nextjs/](https://github.com/hookdeck/webhook-skills/tree/main/skills/circleback-webhooks/examples/nextjs/), [examples/fastapi/](https://github.com/hookdeck/webhook-skills/tree/main/skills/circleback-webhooks/examples/fastapi/).

## Webhook Payload

There are **no event types** and no event-name field: every delivery is one
meeting export, sent when an automation matches a meeting (or when you run the
automation on past meetings). The fields included follow the automation's settings.

| Field | Notes |
| --- | --- |
| `id` | Circleback meeting ID; stable, so use it for idempotency. Link: `https://circleback.ai/meetings/${id}` |
| `name`, `createdAt`, `duration` | Meeting name, ISO timestamp, seconds |
| `url`, `recordingUrl` | Virtual meeting URL; recording URL (valid 24 hours, only if recordings are saved), both nullable |
| `tags`, `icalUid` | Tag names; calendar event UID (nullable) |
| `attendees` | `[{ name, email }]` (both nullable) |
| `notes` | Markdown meeting notes |
| `actionItems` | `[{ id, title, description, assignee: { name, email } | null, status: 'PENDING' | 'DONE' }]` |
| `transcript` | `[{ speaker, text, timestamp }]` (seconds) |
| `insights` | `{ [insightName]: [{ insight, speaker, timestamp }] }` |

## Important Headers

| Header | Description |
| --- | --- |
| `x-signature` | Hex HMAC-SHA256 of the raw body (optional on Circleback's side, recommended) |

## Environment Variables

```bash
CIRCLEBACK_SIGNING_SECRET=your_signing_secret   # Shown in the automation's webhook step

```

## Local Development

```bash
# Start tunnel (no account needed)
npx hookdeck-cli listen 3000 circleback --path /webhooks/circleback

```

Use the printed URL as the endpoint in the automation's **Send webhook request**
step, then send a test request for the most recent meeting.

## Reference Materials

* [references/overview.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/circleback-webhooks/references/overview.md) - What Circleback webhooks are, payload fields
* [references/setup.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/circleback-webhooks/references/setup.md) - Create the automation webhook step, get the signing secret
* [references/verification.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/circleback-webhooks/references/verification.md) - Signature verification details and gotchas