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-Signature header on a Census webhook?
  • How do I handle sync.completed, sync.success, sync.failed, or sync.alert.raised events?
  • 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.

EventDescription
sync.triggeredA sync run has been queued
sync.startedActive work on the sync run has started
sync.completedThe run finished, successful or not; status is ok, or emergency if it failed
sync.successThe run completed successfully
sync.failedThe run failed
sync.alert.raisedA subscribed sync alert fired (adds alert_instance_id, alert_type, message, details, followup_url)
sync.alert.resolvedA subscribed sync alert was resolved (same extra fields)

For the full reference, see Sync lifecycle webhooks.

Important Details

ItemValue
Signature headerX-Signature
AlgorithmHMAC-SHA256 of the raw body, standard base64
SecretShown once when the webhook is created; copy it then
SetupWebhooks tab in the workspace (Add Webhook), or the Census API
Test eventThe 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


Repository

hookdeck/webhook-skills

v0.1.0 · MIT · Updated Nov 3, 2026

View on GitHub →