Agent skill
Census Webhooks Skill
Receive and verify Census (Fivetran Activations) sync webhooks. Use when setting up Census webhook handlers, debugging X-Signature verification, or handling reverse ETL sync events like sync.completed, sync.failed, or sync.alert.raised.
Install this skill
npx skills add hookdeck/webhook-skills --skill census-webhooks
Census is now Fivetran Activations (getcensus.com redirects to fivetran.com). Its sync lifecycle webhooks tell your systems when a reverse ETL sync is queued, running, finished, failed, or alerting. This is separate from the fivetran-webhooks skill, which covers Fivetran's REST API webhooks (X-Fivetran-Signature-256, hex).
When to Use This Skill
- How do I receive Census (Fivetran Activations) webhooks?
- How do I verify the
X-Signatureheader on a Census webhook? - How do I handle
sync.completed,sync.success,sync.failed, orsync.alert.raisedevents? - Why is my Census webhook signature verification failing?
- How do I trigger downstream jobs or alerts when a Census sync finishes or fails?
Verification (core)
Census signs the raw request body with HMAC-SHA256, keyed with the one-time secret shown when you create the webhook (used as raw bytes, no whsec_ handling), and sends the digest as standard base64 (not hex) in X-Signature. There is no timestamp and no prefix.
Node:
const crypto = require('crypto');
function verify(rawBody, signatureHeader, secret) {
if (!signatureHeader || !secret) return false;
const expected = crypto.createHmac('sha256', secret).update(rawBody).digest('base64');
try {
return crypto.timingSafeEqual(Buffer.from(signatureHeader.trim()), Buffer.from(expected));
} catch {
return false; // different lengths
}
}
Python:
import base64, hmac, hashlib
def verify(raw_body: bytes, signature_header: str | None, secret: str) -> bool:
if not signature_header or not secret:
return False
expected = base64.b64encode(
hmac.new(secret.encode(), raw_body, hashlib.sha256).digest()
).decode()
return hmac.compare_digest(signature_header.strip(), expected)
In Express, read the body with express.raw({ type: '*/*' }) so the bytes are intact whatever Content-Type is sent.
For complete handlers with route wiring, event dispatch, and tests, see:
Common Event Types
The event name is in the JSON body (event); there is no event-type header. Every payload has workspace_id, sync_id, sync_run_id, and event.
| Event | Description |
|---|---|
sync.triggered | A sync run has been queued |
sync.started | Active work on the sync run has started |
sync.completed | The run finished, successful or not; status is ok, or emergency if it failed |
sync.success | The run completed successfully |
sync.failed | The run failed |
sync.alert.raised | A subscribed sync alert fired (adds alert_instance_id, alert_type, message, details, followup_url) |
sync.alert.resolved | A subscribed sync alert was resolved (same extra fields) |
For the full reference, see Sync lifecycle webhooks.
Important Details
| Item | Value |
|---|---|
| Signature header | X-Signature |
| Algorithm | HMAC-SHA256 of the raw body, standard base64 |
| Secret | Shown once when the webhook is created; copy it then |
| Setup | Webhooks tab in the workspace (Add Webhook), or the Census API |
| Test event | The docs don't describe one; accept and log unknown event values after verifying |
Environment Variables
CENSUS_WEBHOOK_SECRET=your_webhook_secret # One-time secret shown when the webhook is created
Local Development
# Start tunnel (no account needed)
npx hookdeck-cli listen 3000 census --path /webhooks/census
Reference Materials
- references/overview.md - Census webhook concepts and payloads
- references/setup.md - Creating a webhook and getting the secret
- references/verification.md - Signature verification details