Agent skill

Codat Webhooks Skill

Receive and verify Codat webhooks, delivered through Svix with Standard Webhooks headers (webhook-id, webhook-timestamp, webhook-signature). Use when setting up a Codat webhook endpoint, getting the whsec_ signing secret from the Codat Portal, debugging signature verification, or handling events like company.created, connection.created, connection.connected, read.completed and write.successful.

Install this skill

npx skills add hookdeck/webhook-skills --skill codat-webhooks


Codat is a business data API. Its webhooks report company and connection lifecycle events and data read and write results. Codat delivers them through Svix with the Standard Webhooks header names webhook-id, webhook-timestamp and webhook-signature (not svix-*). Legacy rule-based webhooks are deprecated and not covered.

When to Use This Skill

  • How do I receive Codat webhooks?
  • How do I verify a Codat webhook signature?
  • Where do I find my Codat webhook signing secret?
  • How do I handle company.created, connection.connected, read.completed or write.successful?
  • Why is my Codat webhook-signature verification failing?
  • How do I dedupe Codat webhook retries?

Verification (core)

HeaderValue
webhook-idUnique message ID, the same on every retry
webhook-timestampUnix seconds of this delivery attempt
webhook-signaturev1,<base64 HMAC-SHA256>, space-separated entries (several during rotation)

Signed content is {webhook-id}.{webhook-timestamp}.{raw body}. The key is the base64-decoded part of the endpoint's secret after whsec_. Each endpoint has its own secret. The examples use the standardwebhooks library (npm, PyPI), which enforces a 5-minute timestamp tolerance and compares in constant time. Hookdeck retries and replays resend the original webhook-timestamp, so the library rejects them once they are more than 5 minutes old. If you receive through Hookdeck and need late retries to pass, use the manual check in references/verification.md and drop or widen its timestamp window.

const { Webhook } = require('standardwebhooks');

// rawBody: exact request body string, NOT re-serialised JSON
function verifyCodatWebhook(rawBody, headers, secret = process.env.CODAT_WEBHOOK_SECRET) {
  return new Webhook(secret).verify(rawBody, {
    'webhook-id': headers['webhook-id'],
    'webhook-timestamp': headers['webhook-timestamp'],
    'webhook-signature': headers['webhook-signature'],
  }); // returns the parsed event; throws → respond 400
}

Python: from standardwebhooks.webhooks import Webhook, then Webhook(secret).verify(await request.body(), {...same mapping...}). A dependency-free manual version is in references/verification.md. In Express, read the body with express.raw({ type: '*/*' }) so any content type verifies.

For complete handlers with tests, see examples/express/, examples/nextjs/, examples/fastapi/.

Common Event Types

EventFired when
company.createdA company is created
connection.createdA data connection is created
connection.connectedA connection becomes connected
read.completedA data read finishes
write.successfulA write to the data source succeeds

Full list: references/overview.md and Codat's event types.

Delivery Semantics

  • Dedupe on the webhook-id header, which is the same on every retry.
  • Return a 2xx quickly and process asynchronously.

Environment Variables

CODAT_WEBHOOK_SECRET=whsec_xxxxx   # endpoint's signing secret; handlers fail closed (500) without it

Get it from the Codat Portal: Monitor > Webhooks > Events → your endpoint → Signing secret.

Local Development

# Express / Next.js (use 8000 for FastAPI). No install or account required.
npx hookdeck-cli listen 3000 codat --path /webhooks/codat

Add the printed URL as an endpoint in the Codat Portal (Monitor > Webhooks > Events), choose event types, and create a company or connection to trigger events.

Reference Materials


Repository

hookdeck/webhook-skills

v0.1.0 · MIT · Updated Nov 3, 2026

View on GitHub →